keycloak-aplcache

Changes

Details

diff --git a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/SamlDeploymentContext.java b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/SamlDeploymentContext.java
index b59339c..d145efe 100755
--- a/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/SamlDeploymentContext.java
+++ b/adapters/saml/core/src/main/java/org/keycloak/adapters/saml/SamlDeploymentContext.java
@@ -25,12 +25,21 @@ import org.keycloak.adapters.spi.HttpFacade;
  */
 public class SamlDeploymentContext {
     private SamlDeployment deployment = null;
+    private SamlConfigResolver resolver = null;
 
     public SamlDeploymentContext(SamlDeployment deployment) {
         this.deployment = deployment;
     }
 
+    public SamlDeploymentContext(SamlConfigResolver resolver) {
+        this.resolver = resolver;
+    }
+
     public SamlDeployment resolveDeployment(HttpFacade facade) {
-        return deployment;
+        if (deployment != null) {
+            return deployment;
+        } else {
+            return resolver.resolve(facade.getRequest());
+        }
     }
 }
diff --git a/adapters/saml/servlet-filter/src/main/java/org/keycloak/adapters/saml/servlet/SamlFilter.java b/adapters/saml/servlet-filter/src/main/java/org/keycloak/adapters/saml/servlet/SamlFilter.java
index ab6317a..a06f103 100755
--- a/adapters/saml/servlet-filter/src/main/java/org/keycloak/adapters/saml/servlet/SamlFilter.java
+++ b/adapters/saml/servlet-filter/src/main/java/org/keycloak/adapters/saml/servlet/SamlFilter.java
@@ -19,6 +19,7 @@ package org.keycloak.adapters.saml.servlet;
 
 import org.keycloak.adapters.saml.DefaultSamlDeployment;
 import org.keycloak.adapters.saml.SamlAuthenticator;
+import org.keycloak.adapters.saml.SamlConfigResolver;
 import org.keycloak.adapters.saml.SamlDeployment;
 import org.keycloak.adapters.saml.SamlDeploymentContext;
 import org.keycloak.adapters.saml.SamlSession;
@@ -74,15 +75,12 @@ public class SamlFilter implements Filter {
         String configResolverClass = filterConfig.getInitParameter("keycloak.config.resolver");
         if (configResolverClass != null) {
             try {
-                throw new RuntimeException("Not implemented yet");
-                // KeycloakConfigResolver configResolver = (KeycloakConfigResolver)
-                // context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
-                // deploymentContext = new SamlDeploymentContext(configResolver);
-                // log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.",
-                // configResolverClass);
+                SamlConfigResolver configResolver = (SamlConfigResolver) getClass().getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new SamlDeploymentContext(configResolver);
+                log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
             } catch (Exception ex) {
-                log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[] { configResolverClass, ex.getMessage() });
-                // deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                log.log(Level.WARNING, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[] { configResolverClass, ex.getMessage() });
+                deploymentContext = new SamlDeploymentContext(new DefaultSamlDeployment());
             }
         } else {
             String fp = filterConfig.getInitParameter("keycloak.config.file");
diff --git a/adapters/saml/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java b/adapters/saml/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
index cc3abc2..3f57bff 100755
--- a/adapters/saml/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
+++ b/adapters/saml/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/saml/AbstractSamlAuthenticatorValve.java
@@ -97,13 +97,12 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
         String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver");
         if (configResolverClass != null) {
             try {
-                throw new RuntimeException("Not implemented yet");
-                //KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
-                //deploymentContext = new SamlDeploymentContext(configResolver);
-                //log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
+                SamlConfigResolver configResolver = (SamlConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new SamlDeploymentContext(configResolver);
+                log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
             } catch (Exception ex) {
                 log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", configResolverClass, ex.getMessage());
-                //deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                deploymentContext = new SamlDeploymentContext(new DefaultSamlDeployment());
             }
         } else {
             InputStream is = getConfigInputStream(context);
diff --git a/adapters/saml/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java b/adapters/saml/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
index 4985dfb..1ffa287 100755
--- a/adapters/saml/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
+++ b/adapters/saml/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
@@ -120,13 +120,12 @@ public class SamlServletExtension implements ServletExtension {
         SamlDeploymentContext deploymentContext = null;
         if (configResolverClass != null) {
             try {
-                throw new RuntimeException("Not implemented yet");
-                //configResolver = (SamlConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
-                //deploymentContext = new AdapterDeploymentContext(configResolver);
-                //log.info("Using " + configResolverClass + " to resolve Keycloak configuration on a per-request basis.");
+                configResolver = (SamlConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
+                deploymentContext = new SamlDeploymentContext(configResolver);
+                log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
             } catch (Exception ex) {
                 log.warn("The specified resolver " + configResolverClass + " could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: " + ex.getMessage());
-                //deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                deploymentContext = new SamlDeploymentContext(new DefaultSamlDeployment());
             }
         } else {
             InputStream is = getConfigInputStream(servletContext);
diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java
index f8eb110..4176287 100644
--- a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java
+++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/KeycloakConfigurationServletListener.java
@@ -30,6 +30,7 @@ import org.jboss.logging.Logger;
 import org.keycloak.adapters.AdapterDeploymentContext;
 import org.keycloak.adapters.saml.AdapterConstants;
 import org.keycloak.adapters.saml.DefaultSamlDeployment;
+import org.keycloak.adapters.saml.SamlConfigResolver;
 import org.keycloak.adapters.saml.SamlDeployment;
 import org.keycloak.adapters.saml.SamlDeploymentContext;
 import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
@@ -61,13 +62,12 @@ public class KeycloakConfigurationServletListener implements ServletContextListe
         if (deploymentContext == null) {
             if (configResolverClass != null) {
                 try {
-                    throw new RuntimeException("Not implemented yet");
-                    //configResolver = (SamlConfigResolver) deploymentInfo.getClassLoader().loadClass(configResolverClass).newInstance();
-                    //deploymentContext = new AdapterDeploymentContext(configResolver);
-                    //log.info("Using " + configResolverClass + " to resolve Keycloak configuration on a per-request basis.");
+                    SamlConfigResolver configResolver = (SamlConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
+                    deploymentContext = new SamlDeploymentContext(configResolver);
+                    log.infov("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
                 } catch (Exception ex) {
-                    log.warn("The specified resolver " + configResolverClass + " could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: " + ex.getMessage());
-                    //deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
+                    log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[] { configResolverClass, ex.getMessage() });
+                    deploymentContext = new SamlDeploymentContext(new DefaultSamlDeployment());
                 }
             } else {
                 InputStream is = getConfigInputStream(servletContext);
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/eap/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAPDeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/jboss/eap/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAPDeploymentArchiveProcessor.java
index 28daaeb..71fe996 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/eap/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAPDeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/eap/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAPDeploymentArchiveProcessor.java
@@ -40,7 +40,9 @@ public class EAPDeploymentArchiveProcessor implements ApplicationArchiveProcesso
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
 
-        modifySAMLAdapterConfig(archive);
+        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) {
@@ -61,10 +63,10 @@ public class EAPDeploymentArchiveProcessor implements ApplicationArchiveProcesso
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
 
-    private void modifySAMLAdapterConfig(Archive<?> archive) {
-        if (!archive.contains(DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH)) return;
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
 
-        log.debug("Modifying adapter config " + DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH + " in " + archive.getName());
-        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive);
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
     }
 }
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/eap6/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAP6DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/jboss/eap6/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAP6DeploymentArchiveProcessor.java
index edcbea0..0a26186 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/eap6/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAP6DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/eap6/src/main/java/org/keycloak/testsuite/arquillian/eap/container/EAP6DeploymentArchiveProcessor.java
@@ -42,7 +42,9 @@ public class EAP6DeploymentArchiveProcessor implements ApplicationArchiveProcess
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
 
-        modifySAMLAdapterConfig(archive);
+        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) {
@@ -72,10 +74,10 @@ public class EAP6DeploymentArchiveProcessor implements ApplicationArchiveProcess
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
 
-    private void modifySAMLAdapterConfig(Archive<?> archive) {
-        if (!archive.contains(DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH)) return;
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
 
-        log.debug("Modifying adapter config " + DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH + " in " + archive.getName());
-        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive);
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
     }
 }
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/WildflyDeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/WildflyDeploymentArchiveProcessor.java
index a5ee439..644afcb 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/WildflyDeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/WildflyDeploymentArchiveProcessor.java
@@ -40,7 +40,9 @@ public class WildflyDeploymentArchiveProcessor implements ApplicationArchiveProc
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
 
-        modifySAMLAdapterConfig(archive);
+        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) {
@@ -61,10 +63,10 @@ public class WildflyDeploymentArchiveProcessor implements ApplicationArchiveProc
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
 
-    private void modifySAMLAdapterConfig(Archive<?> archive) {
-        if (!archive.contains(DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH)) return;
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
 
-        log.debug("Modifying adapter config " + DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH + " in " + archive.getName());
-        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive);
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
     }
 }
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly10/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly10DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly10/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly10DeploymentArchiveProcessor.java
index 5c61ab5..4d57817 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly10/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly10DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly10/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly10DeploymentArchiveProcessor.java
@@ -41,7 +41,9 @@ public class Wildfly10DeploymentArchiveProcessor implements ApplicationArchivePr
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
         
-        modifySAMLAdapterConfig(archive);
+        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) {
@@ -62,10 +64,10 @@ public class Wildfly10DeploymentArchiveProcessor implements ApplicationArchivePr
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
 
-    private void modifySAMLAdapterConfig(Archive<?> archive) {
-        if (!archive.contains(DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH)) return;
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
         
-        log.debug("Modifying adapter config " + DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH + " in " + archive.getName());
-        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive);
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
     }
 }
diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly9DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly9DeploymentArchiveProcessor.java
index ef22947..b659b88 100644
--- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly9DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/src/main/java/org/keycloak/testsuite/arquillian/wildfly/container/Wildfly9DeploymentArchiveProcessor.java
@@ -41,7 +41,9 @@ public class Wildfly9DeploymentArchiveProcessor implements ApplicationArchivePro
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH);
         modifyOIDCAdapterConfig(archive, DeploymentArchiveProcessorUtils.ADAPTER_CONFIG_PATH_JS);
         
-        modifySAMLAdapterConfig(archive);
+        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) {
@@ -62,10 +64,10 @@ public class Wildfly9DeploymentArchiveProcessor implements ApplicationArchivePro
         DeploymentArchiveProcessorUtils.modifyOIDCAdapterConfig(archive, adapterConfigPath);
     }
 
-    private void modifySAMLAdapterConfig(Archive<?> archive) {
-        if (!archive.contains(DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH)) return;
+    private void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        if (!archive.contains(adapterConfigPath)) return;
         
-        log.debug("Modifying adapter config " + DeploymentArchiveProcessorUtils.SAML_ADAPTER_CONFIG_PATH + " in " + archive.getName());
-        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive);
+        log.debug("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
+        DeploymentArchiveProcessorUtils.modifySAMLAdapterConfig(archive, adapterConfigPath);
     }
 }
diff --git a/testsuite/integration-arquillian/test-apps/servlets/pom.xml b/testsuite/integration-arquillian/test-apps/servlets/pom.xml
index 8ed980f..ac6fc5b 100644
--- a/testsuite/integration-arquillian/test-apps/servlets/pom.xml
+++ b/testsuite/integration-arquillian/test-apps/servlets/pom.xml
@@ -50,6 +50,14 @@
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-saml-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-core-public</artifactId>
+        </dependency>
     </dependencies>
 
-</project>
\ No newline at end of file
+</project>
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
new file mode 100644
index 0000000..559a4ef
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlMultiTenantResolver.java
@@ -0,0 +1,60 @@
+/*
+ * 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.adapter.servlet;
+
+import java.io.InputStream;
+import org.keycloak.adapters.saml.SamlConfigResolver;
+import org.keycloak.adapters.saml.SamlDeployment;
+import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
+import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
+import org.keycloak.adapters.spi.HttpFacade;
+import org.keycloak.saml.common.exceptions.ParsingException;
+
+/**
+ *
+ * @author rmartinc
+ */
+public class SamlMultiTenantResolver implements SamlConfigResolver {
+
+    @Override
+    public SamlDeployment resolve(HttpFacade.Request request) {
+        String realm = request.getQueryParamValue("realm");
+        if (realm == null) {
+            throw new IllegalStateException("Not able to resolve realm from the request path!");
+        }
+
+        InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak-saml.xml");
+        if (is == null) {
+            throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak-saml.xml");
+        }
+
+        ResourceLoader loader = new ResourceLoader() {
+            @Override
+            public InputStream getResourceAsStream(String path) {
+                return getClass().getResourceAsStream(path);
+            }
+        };
+        
+        try {
+            return new DeploymentBuilder().build(is, loader);
+        } catch (ParsingException e) {
+            throw new IllegalStateException("Cannot load SAML deployment", e);
+        }
+    }
+
+}
diff --git a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
index 2c0b17d..e795526 100755
--- a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
+++ b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
@@ -205,4 +205,14 @@ public class SendUsernameServlet extends HttpServlet {
 
         return output;
     }
+
+    @GET
+    @Path("getAssertionIssuer")
+    public Response getAssertionIssuer() throws IOException {
+        sentPrincipal = httpServletRequest.getUserPrincipal();
+        SamlPrincipal principal = (SamlPrincipal) sentPrincipal;
+        return Response.ok(principal.getAssertion().getIssuer().getValue())
+                .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_TYPE + ";charset=UTF-8").build();
+    }
+
 }
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
new file mode 100644
index 0000000..bb08f88
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant1Saml.java
@@ -0,0 +1,52 @@
+/*
+ * 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.adapter.page;
+
+import java.net.MalformedURLException;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+import static org.keycloak.testsuite.util.WaitUtils.pause;
+
+/**
+ * @author rmartinc
+ */
+public class MultiTenant1Saml extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "multi-tenant-saml";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        try {
+            return new URL(url + "/?realm=tenant1");
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+    
+    @Override
+    public void logout() {
+        driver.navigate().to(getUriBuilder().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
new file mode 100644
index 0000000..e2623d1
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MultiTenant2Saml.java
@@ -0,0 +1,52 @@
+/*
+ * 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.adapter.page;
+
+import java.net.MalformedURLException;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+import static org.keycloak.testsuite.util.WaitUtils.pause;
+
+/**
+ * @author rmartinc
+ */
+public class MultiTenant2Saml extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "multi-tenant-saml";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        try {
+            return new URL(url + "/?realm=tenant2");
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+    
+    @Override
+    public void logout() {
+        driver.navigate().to(getUriBuilder().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/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
index 90a9850..2ca1880 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
@@ -37,9 +37,16 @@ import org.keycloak.testsuite.utils.io.IOUtil;
 import org.keycloak.util.JsonSerialization;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.NodeList;
 
 import java.io.File;
 import java.io.IOException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
 import org.jboss.logging.Logger;
 import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.isEAP6AppServer;
 import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.isEAPAppServer;
@@ -81,6 +88,8 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
     public static final String ADAPTER_CONFIG_PATH_JS = "/keycloak.json";
     public static final String SAML_ADAPTER_CONFIG_PATH = "/WEB-INF/keycloak-saml.xml";
     public static final String JBOSS_DEPLOYMENT_XML_PATH = "/WEB-INF/jboss-deployment-structure.xml";
+    public static final String SAML_ADAPTER_CONFIG_PATH_TENANT1 = "/WEB-INF/classes/tenant1-keycloak-saml.xml";
+    public static final String SAML_ADAPTER_CONFIG_PATH_TENANT2 = "/WEB-INF/classes/tenant2-keycloak-saml.xml";
 
     @Inject
     @ClassScoped
@@ -131,15 +140,17 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
         modifyAdapterConfig(archive, ADAPTER_CONFIG_PATH_TENANT2, relative);
         modifyAdapterConfig(archive, ADAPTER_CONFIG_PATH_JS, relative);
         modifyAdapterConfig(archive, SAML_ADAPTER_CONFIG_PATH, relative);
+        modifyAdapterConfig(archive, SAML_ADAPTER_CONFIG_PATH_TENANT1, relative);
+        modifyAdapterConfig(archive, SAML_ADAPTER_CONFIG_PATH_TENANT2, relative);
     }
 
     protected void modifyAdapterConfig(Archive<?> archive, String adapterConfigPath, boolean relative) {
         if (archive.contains(adapterConfigPath)) {
             log.info("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
-            if (adapterConfigPath.equals(SAML_ADAPTER_CONFIG_PATH)) { // SAML adapter config
+            if (adapterConfigPath.endsWith(".xml")) { // SAML adapter config
                 log.info("Modifying saml adapter config in " + archive.getName());
 
-                Document doc = loadXML(archive.get("WEB-INF/keycloak-saml.xml").getAsset().openStream());
+                Document doc = loadXML(archive.get(adapterConfigPath).getAsset().openStream());
                 if (AUTH_SERVER_SSL_REQUIRED) {
                     modifyDocElementAttribute(doc, "SingleSignOnService", "bindingUrl", "8080", System.getProperty("auth.server.https.port"));
                     modifyDocElementAttribute(doc, "SingleSignOnService", "bindingUrl", "http", "https");
@@ -225,7 +236,6 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
         }
 
         if (testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class) && archive.contains(JBOSS_DEPLOYMENT_XML_PATH)) {
-
             addFilterDependencies(archive, testClass);
 
             //We need to add filter declaration to web.xml
@@ -240,6 +250,20 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 
             filter.appendChild(filterName);
             filter.appendChild(filterClass);
+            
+            // check if there was a resolver for OIDC and set as a filter param
+            String keycloakResolverClass = getKeycloakResolverClass(webXmlDoc);
+            if (keycloakResolverClass != null) {
+                Element initParam = webXmlDoc.createElement("init-param");
+                Element paramName = webXmlDoc.createElement("param-name");
+                paramName.setTextContent("keycloak.config.resolver");
+                Element paramValue = webXmlDoc.createElement("param-value");
+                paramValue.setTextContent(keycloakResolverClass);
+                initParam.appendChild(paramName);
+                initParam.appendChild(paramValue);
+                filter.appendChild(initParam);
+            }
+            
             appendChildInDocument(webXmlDoc, "web-app", filter);
 
             filter.appendChild(filterName);
@@ -292,4 +316,21 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 
         archive.add(new StringAsset((documentToString(webXmlDoc))), WEBXML_PATH);
     }
+    
+    private String getKeycloakResolverClass(Document doc) {
+        try {
+            XPathFactory factory = XPathFactory.newInstance();
+            XPath xpath = factory.newXPath();
+            XPathExpression expr = xpath.compile("//web-app/context-param[param-name='keycloak.config.resolver']/param-value/text()");
+            NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+            if (nodes != null && nodes.getLength() > 0) {
+                return nodes.item(0).getNodeValue();
+            }
+        } catch(DOMException e) {
+            throw new IllegalStateException(e);
+        } catch (XPathExpressionException e) {
+            throw new IllegalStateException(e);
+        }
+        return null;
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant1.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant1.java
new file mode 100644
index 0000000..274937d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant1.java
@@ -0,0 +1,28 @@
+/*
+ * 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.auth.page.login;
+
+/**
+ * @author rmartinc
+ */
+public class SAMLPostLoginTenant1 extends Login {
+    SAMLPostLoginTenant1() {
+        setProtocol(LOGIN_ACTION);
+        setAuthRealm("tenant1");
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant2.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant2.java
new file mode 100644
index 0000000..a933d60
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLPostLoginTenant2.java
@@ -0,0 +1,28 @@
+/*
+ * 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.auth.page.login;
+
+/**
+ * @author rmartinc
+ */
+public class SAMLPostLoginTenant2 extends Login {
+    SAMLPostLoginTenant2() {
+        setProtocol(LOGIN_ACTION);
+        setAuthRealm("tenant2");
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
index 6220110..ba694bb 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
@@ -32,6 +32,7 @@ import java.io.IOException;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.util.List;
+import org.jboss.shrinkwrap.api.asset.UrlAsset;
 
 import org.junit.Assert;
 import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
@@ -110,6 +111,49 @@ public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
         return deployment;
     }
 
+    public static WebArchive samlServletDeploymentMultiTenant(String name, String webXMLPath, 
+            String config1, String config2,
+            String keystore1, String keystore2, Class... servletClasses) {
+        String baseSAMLPath = "/adapter-test/keycloak-saml/";
+        String webInfPath = baseSAMLPath + name + "/WEB-INF/";
+
+        URL webXML = AbstractServletsAdapterTest.class.getResource(baseSAMLPath + webXMLPath);
+        Assert.assertNotNull("web.xml should be in " + baseSAMLPath + webXMLPath, webXML);
+
+        WebArchive deployment = ShrinkWrap.create(WebArchive.class, name + ".war")
+                .addClasses(servletClasses)
+                .addAsWebInfResource(jbossDeploymentStructure, JBOSS_DEPLOYMENT_STRUCTURE_XML);
+
+        String webXMLContent;
+        try {
+            webXMLContent = IOUtils.toString(webXML.openStream(), Charset.forName("UTF-8"))
+                    .replace("%CONTEXT_PATH%", name);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        deployment.add(new StringAsset(webXMLContent), "/WEB-INF/web.xml");
+
+        // add the xml for each tenant in classes
+        URL config1Url = AbstractServletsAdapterTest.class.getResource(webInfPath + config1);
+        Assert.assertNotNull("config1Url should be in " + webInfPath + config1, config1Url);
+        deployment.add(new UrlAsset(config1Url), "/WEB-INF/classes/" + config1);
+        URL config2Url = AbstractServletsAdapterTest.class.getResource(webInfPath + config2);
+        Assert.assertNotNull("config2Url should be in " + webInfPath + config2, config2Url);
+        deployment.add(new UrlAsset(config2Url), "/WEB-INF/classes/" + config2);
+        
+        // add the keystores for each tenant in classes
+        URL keystore1Url = AbstractServletsAdapterTest.class.getResource(webInfPath + keystore1);
+        Assert.assertNotNull("keystore1Url should be in " + webInfPath + keystore1, keystore1Url);
+        deployment.add(new UrlAsset(keystore1Url), "/WEB-INF/classes/" + keystore1);
+        URL keystore2Url = AbstractServletsAdapterTest.class.getResource(webInfPath + keystore2);
+        Assert.assertNotNull("keystore2Url should be in " + webInfPath + keystore2, keystore2Url);
+        deployment.add(new UrlAsset(keystore2Url), "/WEB-INF/classes/" + keystore2);
+
+        addContextXml(deployment, name);
+
+        return deployment;
+    }
+
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(IOUtil.loadRealm("/adapter-test/demorealm.json"));
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 18df393..0f0e79b 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
@@ -135,6 +135,8 @@ import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
 import org.keycloak.testsuite.arquillian.containers.ContainerConstants;
 import org.keycloak.testsuite.auth.page.login.Login;
 import org.keycloak.testsuite.auth.page.login.SAMLIDPInitiatedLogin;
+import org.keycloak.testsuite.auth.page.login.SAMLPostLoginTenant1;
+import org.keycloak.testsuite.auth.page.login.SAMLPostLoginTenant2;
 import org.keycloak.testsuite.page.AbstractPage;
 import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
 import org.keycloak.testsuite.util.SamlClient;
@@ -255,6 +257,18 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
     @Page
     protected EcpSP ecpSPPage;
 
+    @Page
+    protected MultiTenant1Saml mutiTenant1SamlPage;
+    
+    @Page
+    protected MultiTenant2Saml mutiTenant2SamlPage;
+    
+    @Page
+    protected SAMLPostLoginTenant1 tenant1RealmSAMLPostLoginPage;
+    
+    @Page
+    protected SAMLPostLoginTenant2 tenant2RealmSAMLPostLoginPage;
+
     public static final String FORBIDDEN_TEXT = "HTTP status code: 403";
     public static final String WEBSPHERE_FORBIDDEN_TEXT = "Error reported: 403";
 
@@ -399,9 +413,19 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
         return samlServletDeployment(EcpSP.DEPLOYMENT_NAME, SendUsernameServlet.class);
     }
 
+    @Deployment(name = MultiTenant1Saml.DEPLOYMENT_NAME)
+    protected static WebArchive multiTenant() {
+        return samlServletDeploymentMultiTenant(MultiTenant1Saml.DEPLOYMENT_NAME, "multi-tenant-saml/WEB-INF/web.xml", 
+                "tenant1-keycloak-saml.xml", "tenant2-keycloak-saml.xml",
+                "keystore-tenant1.jks", "keystore-tenant2.jks", 
+                SendUsernameServlet.class, SamlMultiTenantResolver.class);
+    }
+
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(IOUtil.loadRealm("/adapter-test/keycloak-saml/testsaml.json"));
+        testRealms.add(IOUtil.loadRealm("/adapter-test/keycloak-saml/tenant1-realm.json"));
+        testRealms.add(IOUtil.loadRealm("/adapter-test/keycloak-saml/tenant2-realm.json"));
     }
 
     @Override
@@ -436,6 +460,14 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
                 || driver.getPageSource().contains(FORBIDDEN_TEXT)
                 || driver.getPageSource().contains(WEBSPHERE_FORBIDDEN_TEXT)); // WebSphere
     }
+    
+    private void assertFailedLogin(AbstractPage page, UserRepresentation user, Login loginPage) {
+        page.navigateTo();
+        assertCurrentUrlStartsWith(loginPage);
+        loginPage.form().login(user);
+        // we remain in login
+        assertCurrentUrlStartsWith(loginPage);
+    }
 
     private void assertSuccessfulLogin(AbstractPage page, UserRepresentation user, Login loginPage, String expectedString) {
         page.navigateTo();
@@ -554,6 +586,42 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
         assertSuccessfulLogin(employeeAcsServletPage, bburkeUser, testRealmSAMLPostLoginPage, "principal=bburke");
     }
 
+    @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);
+    }
+    
+    @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);
+    }
+
     private static final KeyPair NEW_KEY_PAIR = KeyUtils.generateRsaKeyPair(1024);
     private static final String NEW_KEY_PRIVATE_KEY_PEM = PemUtils.encodeKey(NEW_KEY_PAIR.getPrivate());
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/jboss-deployment-structure.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/jboss-deployment-structure.xml
index 9356226..1edfc3e 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/jboss-deployment-structure.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/jboss-deployment-structure.xml
@@ -26,7 +26,8 @@
             <!--required by SAML test servlets-->
             <module name="org.keycloak.keycloak-adapter-spi" />
             <module name="org.keycloak.keycloak-saml-core" />
+            <module name="org.keycloak.keycloak-saml-core-public" />
             
         </dependencies>
     </deployment>
-</jboss-deployment-structure>
\ No newline at end of file
+</jboss-deployment-structure>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant1.jks b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant1.jks
new file mode 100644
index 0000000..c3ad85b
Binary files /dev/null and b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant1.jks differ
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant2.jks b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant2.jks
new file mode 100644
index 0000000..d2b3d9b
Binary files /dev/null and b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/keystore-tenant2.jks differ
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant1-keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant1-keycloak-saml.xml
new file mode 100644
index 0000000..cd3ae8b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant1-keycloak-saml.xml
@@ -0,0 +1,36 @@
+<keycloak-saml-adapter>
+    <SP entityID="multi-tenant"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp?realm=tenant1"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true">
+                <KeyStore resource="/keystore-tenant1.jks" password="changeit">
+                    <PrivateKey alias="multi-tenant" password="changeit"/>
+                    <Certificate alias="multi-tenant"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp"
+             signatureAlgorithm="RSA_SHA256">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 validateAssertionSignature="false"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/tenant1/protocol/saml"/>
+            <SingleLogoutService signRequest="true"
+                                 signResponse="true"
+                                 validateRequestSignature="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 responseBinding="POST"
+                                 postBindingUrl="http://localhost:8080/auth/realms/tenant1/protocol/saml"
+                                 redirectBindingUrl="http://localhost:8080/auth/realms/tenant1/protocol/saml"/>
+        </IDP>
+    </SP>
+</keycloak-saml-adapter>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant2-keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant2-keycloak-saml.xml
new file mode 100644
index 0000000..4058f4d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/tenant2-keycloak-saml.xml
@@ -0,0 +1,36 @@
+<keycloak-saml-adapter>
+    <SP entityID="multi-tenant"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp?realm=tenant2"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true">
+                <KeyStore resource="/keystore-tenant2.jks" password="changeit">
+                    <PrivateKey alias="multi-tenant" password="changeit"/>
+                    <Certificate alias="multi-tenant"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp"
+             signatureAlgorithm="RSA_SHA256">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 validateAssertionSignature="false"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/tenant2/protocol/saml"/>
+            <SingleLogoutService signRequest="true"
+                                 signResponse="true"
+                                 validateRequestSignature="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 responseBinding="POST"
+                                 postBindingUrl="http://localhost:8080/auth/realms/tenant2/protocol/saml"
+                                 redirectBindingUrl="http://localhost:8080/auth/realms/tenant2/protocol/saml"/>
+        </IDP>
+    </SP>
+</keycloak-saml-adapter>
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
new file mode 100644
index 0000000..1720657
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/multi-tenant-saml/WEB-INF/web.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>%CONTEXT_PATH%</module-name>
+
+    <servlet>
+        <servlet-name>javax.ws.rs.core.Application</servlet-name>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>javax.ws.rs.core.Application</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+    <error-page>
+        <location>/error.html</location>
+    </error-page>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Application</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>user</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>KEYCLOAK-SAML</auth-method>
+        <realm-name>demo</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>manager</role-name>
+    </security-role>
+    
+    <context-param>
+        <param-name>keycloak.config.resolver</param-name>
+        <param-value>org.keycloak.testsuite.adapter.servlet.SamlMultiTenantResolver</param-value>
+    </context-param>
+</web-app>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant1-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant1-realm.json
new file mode 100644
index 0000000..99c13cf
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant1-realm.json
@@ -0,0 +1,73 @@
+{
+    "id": "tenant1",
+    "realm": "tenant1",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ]
+        },
+        {
+            "username" : "user-tenant1",
+            "enabled": true,
+            "email" : "user-tenant1@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant1" }
+            ],
+            "realmRoles": [ "user" ]
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "multi-tenant",
+            "name": "multi-tenant",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "frontchannelLogout": true,
+            "baseUrl": "http://localhost:8080/multi-tenant-saml/",
+            "redirectUris": [
+                "http://localhost:8080/multi-tenant-saml/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant1",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant1",
+                "saml_single_logout_service_url_post": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant1",
+                "saml_single_logout_service_url_redirect": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant1",
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.authnstatement": "true",
+                "saml.signing.certificate": "MIICwTCCAakCBgFjh8UCJDANBgkqhkiG9w0BAQsFADAkMSIwIAYDVQQDDBltdWx0aS10ZW5hbnQtc2FtbC10ZW5hbnQxMB4XDTE4MDUyMjEyMTIwNVoXDTI4MDUyMjEyMTM0NVowJDEiMCAGA1UEAwwZbXVsdGktdGVuYW50LXNhbWwtdGVuYW50MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJFoRVHp55NFqAbzQ9WRWKNP3yUrAT5HT0klZg8ttuMq5JhuGvl5aADnoOUhD/SbJST73ObF3JMqRSW8899yKByYxG5HH03KEpbGbB+gT2dYwzHSqN7E2G0h+VSpfQvjOyMFdRQORbBicnTVN+a828JlTf7uxmQ2ifgKuuZgUtUydLRh9vbcbYMP0sqKBNXAJKzJuqv6yQPmn78OGvtDZz+oThcJ44QQ19A/PaNrDNPKvjQsibfBfyV/tCaRs6UKIdROy272ZDL8aqVrZqnFzF5mTNOa+Ko91UTLaWKsSxBPk3Tv2tZJkeoWztFBOjVEV3Uz76BraUSZeg78oNfuuJMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEABVma/QDyE2ZyNZuFjoJ9+FuUlTElcoHsId1W6UY1tfpi4kqBneLtxJfOUtCHveogNgFaJJHiAfJDtpj3iNuEtziyRQuSlg7NiHHhKcxAUpBBs6So2zlTfTrwC647IOQWPFQRTQruJJnSMQHQ0PRBG6HBQKpVtltk5PEMOi0YK/y0XxMMqi2/0TCyVEuQlLbu+gN95xIkXTh90dte1Vh7PJk54Mby9Yk3Q0Qq0aVF805/GimA9o/rGYSruH6Tj8qGp6rvVN6StM4o9sDnZIEcZMEWTvaeLZxQ0A8TD4NWgp+M2MmRH/hahyOkiYL3nv/S/MTe0VmC908h6+R0QqGTYQ==",
+                "saml.signing.private.key": "MIIEowIBAAKCAQEAkWhFUennk0WoBvND1ZFYo0/fJSsBPkdPSSVmDy224yrkmG4a+XloAOeg5SEP9JslJPvc5sXckypFJbzz33IoHJjEbkcfTcoSlsZsH6BPZ1jDMdKo3sTYbSH5VKl9C+M7IwV1FA5FsGJydNU35rzbwmVN/u7GZDaJ+Aq65mBS1TJ0tGH29txtgw/SyooE1cAkrMm6q/rJA+afvw4a+0NnP6hOFwnjhBDX0D89o2sM08q+NCyJt8F/JX+0JpGzpQoh1E7LbvZkMvxqpWtmqcXMXmZM05r4qj3VRMtpYqxLEE+TdO/a1kmR6hbO0UE6NURXdTPvoGtpRJl6Dvyg1+64kwIDAQABAoIBAA3Xrlm4+cnEZNWcjQWk25pYfTbNnEWwhjTBcbDaOkHwEGkOelTroOINKv0FI762klet/n6dsXz1FjYcgd7wwC7QwEp7TNib9x8RbrOoEEcXZSW2F0t10+C3zkOoCvZ5wGR6HYY2QZ4kER9cOQEnU4hzGnS9iHd71bCeXOKXousWyJGMg3Bl5MSIqNabSIMNTqOHVR8TEMOSGjkYQO4oTP+YcySbIatAVj95aMGTUWJZxMVDBHt2CyjvKIRq1nJV8nhuUH3ui2wZJIscjPuSWFHAuB/dDli2XK8aZUyMGrbD2AjFhegrG73/w71QvCqZ14hOiaX3SCRKJFqwsZ+iW/kCgYEA2emTez8HDvxW5dhbV+qIl+PSBhGBz7w0Wr6dc7Nakriue9ad3lBr2LjrI2hLUHcrS/TKhnyLfe67lODysYPd9HHwFDMxgXQLTrZudQkUt8ebNi//1MGRuZ1Z6W/7MW9oN/JwoqWcYkXN+4bIQyTkKQA4lvkaBOuKEIFUn059I50CgYEAqtJ56pc9gJDB+nnJ778dYlLLxjsGIZawWXf9BgxnPnoIRn5ejOusfB/BExeLxngmMOxNI0IAL59NmkNPCse/SSXGM8GS2llSqEtZBCtTfYuhhyAhoqA4qwrm9WJybuYaKeBllmmrbOX/TmzhC0dwy0anUG0tm4NFTV8AK95hje8CgYEAm3woeWYteSngLzxDYOW99PLfpujTARC/Ioij/CxbUhloloA6QKiNayP201rVcmK1iArwfylats6jFcW0Jal7s7GgpikpB79vWgido/CI0eEhBHcXSg2cFx8JSqFWUJ23dUQNzl/wx8YbBX/UYORv0DmSJ1cyk5Qk/UXqxYjRjZkCgYACwfcZ5Gsnwi5/fqvV5P3ycme7wYQt0qLyLs+040pfZdTwXmXkXIGiV1jkmAK3p4TmUUpFgXFDU40LKn8CK4tZAPUcLMnUIJEHCoBbYt+sLS7kYY5pc7C2giyMVZSHWcueVXMOZJJR5byjZXqUlgiqH2/gCoMr+YiK4Te9fY+RnQKBgGekolH+YH4HiUtYKn5qGKveiSpOy/X90zMLLKFWVjngsYEqDj7Bi8S8t1MReaMPMMo/sEBwYE+jomnCH3Dj+HlKf00WjFa/5pbFWqbiIcGGdXslfJSNSDeQ5bpdc6MqFnumZHumExqUGGGXUxVXnhf2NyhfGixNiukWXAIhzlW2"
+            }
+        }
+    ]
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant2-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant2-realm.json
new file mode 100644
index 0000000..97deab5
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/tenant2-realm.json
@@ -0,0 +1,73 @@
+{
+    "id": "tenant2",
+    "realm": "tenant2",
+    "enabled": true,
+    "accessTokenLifespan": 3000,
+    "accessCodeLifespan": 10,
+    "accessCodeLifespanUserAction": 6000,
+    "sslRequired": "external",
+    "registrationAllowed": false,
+    "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "requiredCredentials": [ "password" ],
+    "users" : [
+        {
+            "username" : "bburke@redhat.com",
+            "enabled": true,
+            "email" : "bburke@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "password" }
+            ],
+            "realmRoles": [ "user" ]
+        },
+        {
+            "username" : "user-tenant2",
+            "enabled": true,
+            "email" : "user-tenant2@redhat.com",
+            "firstName": "Bill",
+            "lastName": "Burke",
+            "credentials" : [
+                { "type" : "password",
+                    "value" : "user-tenant2" }
+            ],
+            "realmRoles": [ "user" ]
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            }
+        ]
+    },
+    "clients": [
+        {
+            "clientId": "multi-tenant",
+            "name": "multi-tenant",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "frontchannelLogout": true,
+            "baseUrl": "http://localhost:8080/multi-tenant-saml/",
+            "redirectUris": [
+                "http://localhost:8080/multi-tenant-saml/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant2",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant2",
+                "saml_single_logout_service_url_post": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant2",
+                "saml_single_logout_service_url_redirect": "http://localhost:8080/multi-tenant-saml/saml?realm=tenant2",
+                "saml.server.signature": "true",
+                "saml.client.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.authnstatement": "true",
+                "saml.signing.certificate": "MIICpzCCAY8CBgFjh/X1zDANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxtdWx0aS10ZW5hbnQwHhcNMTgwNTIyMTMwNTMzWhcNMjgwNTIyMTMwNzEzWjAXMRUwEwYDVQQDDAxtdWx0aS10ZW5hbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEIM1mJ9KE9OtVDl+6N9Cyg1byP8g8NARWIxstKR69eb9MlrXdzAZtv6S/DyLHuNpjX1DXisuHYHn4Si/2xa0XpRos151lOrk4YrJPokQWz+/Qej3vpJOeWC/EXeISs59t3zrUf/v2OtI57lln7ItABe6+nbTmGuLVCXYxHTaLxo4PRMh9IdsWIWjGi1F4uUR1P253ty9GgYFiRzNMxT9M4yOc5nXqih0kid7iZp+Idz1qLdxphgwUY5ElV4aBy1g5eudll8UFsGqaYUNC+V048BRoGyjstzoN8nYDN7yn89Vj5mjEzPH+FQwd1YlT2f7jH92UMBDdHpWrVOEF0DPVAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACaadxu5ap+jr1wsXUX7KrrS5zc5yrNndEduFRLCetqeQ2hAmQkawqVDJnbjGH+uK5pNQ9Qk+ez77hbjMd8TlDwWD6wKdnIgZybxZ8WQi2/IWGXhrHwyITKSJukG1aDu1c9gwO9ho8J17bjpiaINx35s6Gf+iAttwv+Az7DytU42nhXxbSIgG4kb/RQkqOyIagCDJtExUgAs0mdG/Qm0uIMBQ3OZon06tAkj8H2M6PagRHDxIvCuu+MvOzv7WKOtOBP8p/cw5+1tagb9zO7U5yzT9iexYKfn5soU80sbUFgy5PZPq5MEF/xqzgwJdZVkRk0XAcIDTLjwquxd0R+u9tg=",
+                "saml.signing.private.key": "MIIEpAIBAAKCAQEAxCDNZifShPTrVQ5fujfQsoNW8j/IPDQEViMbLSkevXm/TJa13cwGbb+kvw8ix7jaY19Q14rLh2B5+Eov9sWtF6UaLNedZTq5OGKyT6JEFs/v0Ho976STnlgvxF3iErOfbd861H/79jrSOe5ZZ+yLQAXuvp205hri1Ql2MR02i8aOD0TIfSHbFiFoxotReLlEdT9ud7cvRoGBYkczTMU/TOMjnOZ16oodJIne4mafiHc9ai3caYYMFGORJVeGgctYOXrnZZfFBbBqmmFDQvldOPAUaBso7Lc6DfJ2Aze8p/PVY+ZoxMzx/hUMHdWJU9n+4x/dlDAQ3R6Vq1ThBdAz1QIDAQABAoIBACKrbcOuLG+mX+dUOCXR8glsYDVIgxvpUg7r+8Ta7P0vhVqDlbiUdVp3Myc3BL3rdmd0lPTVKy9OJaF3c80amoOAgwUERGV9oPpPsBeVppWlwk3HHiW7oQCvtBnxQqJtsDQa7upbiW24bishcBqH3QG/SrnVZQH8JLbmCkeaU2cXrbqZchGTj4nMVlHaFgOqb9A6y911Jlbyh9F2lP5aNRPekcNUV17+JhxKxCeyPesrvwey4DcbTWC0Li+BtnO2YwGADRteiz23g8xz+miQO4vTcOy/rctgNkmlo6U9vSwfuvRmMlVy1q1JnAiyATr/nzAz5zYPSHuQjeA/i9vZU00CgYEA9fSKyd3l+AZDPivVb+uqOu6pWAs3UoVZwE7SeEvvt93o+eOMWn+e9K5XimCfT/EM+B09L186hx5RL46ZNuUGWDtCSZXWpD5MRIt7e3gLSmVUyg9BM5UJk7zRwi933A5+VqwpTw/ivT0XSVbErRPSirmbXLO2n+i00a7J9BmsP/cCgYEAzCNRkaiW4dEMGsdACa+FW+QATvGXtcW10xBD3NuvBo8XvNRf/d2o3Pd99cljTlKiBLMZYap3+AuJzHtHRb9bEhJDKmitVlZpcNCcC0RA3t+9CfNdvHCrpW+lZEdVUFmIbkvgkqeFG2e7o03Q2G1avDnjzQxCworO5XJQMBcYD5MCgYEA4RXSjbsM4laY4ySqR6qcNyKCx5g8IMD4yg1Yf86+qr3ioA2mPIvepH2Ij5KtOTOYctgPTnMP1Ofh1Gvju2EM1WIl38HIlLaOhYxAjVXmv0bMub4MJXCXOyTpsZRPVIvPAvK7OyeGkTh/PxaxFtO1Mk955vRwhRcpo1saZtG32TECgYEAtyWg0xv8cpEJWSUWkRoGfdDrbehXAmBlpv1axVXbi/jphSLNFIjALa9mNRP/oo+EiM7eoL8+by567RhVc4AhBu+Xjv7nNSTF6M9gkMMlqE/33GuZ160GcqDeND/DjRkmzD4LN8hQJaxFrlfsXaCO3XzaomazprK+uSB8TQkLLz0CgYAWja2b42bn9vqXWnhfOorgD+HaBpVhhOAzyJu+U2YJViOSdtZpUgQCmz8XUOm5en2CwAIFOG0NvKtpLMmqNKnC7Gigg6ow2hw0v+VaH2trU295Z/lkRaX6fUT//My04aXPHg5bR3DXyd3YKOUV1MfvpTQelG1MKLX3YaMGxcmZ5w=="
+            }
+        }
+    ]
+}
diff --git a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/arquillian/DeploymentArchiveProcessorUtils.java b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/arquillian/DeploymentArchiveProcessorUtils.java
index c5dece7..45933f4 100644
--- a/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/arquillian/DeploymentArchiveProcessorUtils.java
+++ b/testsuite/integration-arquillian/util/src/main/java/org/keycloak/testsuite/utils/arquillian/DeploymentArchiveProcessorUtils.java
@@ -18,6 +18,11 @@ package org.keycloak.testsuite.utils.arquillian;
 
 import java.io.File;
 import java.io.IOException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
 import org.jboss.arquillian.test.spi.TestClass;
 import org.jboss.logging.Logger;
 import org.jboss.shrinkwrap.api.Archive;
@@ -28,8 +33,10 @@ import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.testsuite.utils.annotation.UseServletFilter;
 import org.keycloak.testsuite.utils.io.IOUtil;
 import org.keycloak.util.JsonSerialization;
+import org.w3c.dom.DOMException;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 
 /**
  *
@@ -49,6 +56,8 @@ public class DeploymentArchiveProcessorUtils {
     public static final String ADAPTER_CONFIG_PATH_JS = "/keycloak.json";
     public static final String SAML_ADAPTER_CONFIG_PATH = "/WEB-INF/keycloak-saml.xml";
     public static final String JBOSS_DEPLOYMENT_XML_PATH = "/WEB-INF/jboss-deployment-structure.xml";
+    public static final String SAML_ADAPTER_CONFIG_PATH_TENANT1 = "/WEB-INF/classes/tenant1-keycloak-saml.xml";
+    public static final String SAML_ADAPTER_CONFIG_PATH_TENANT2 = "/WEB-INF/classes/tenant2-keycloak-saml.xml";
 
     /**
      * @return true iff archive's name equals run-on-server-classes.war
@@ -85,6 +94,19 @@ public class DeploymentArchiveProcessorUtils {
         filter.appendChild(filterName);
         filter.appendChild(filterClass);
 
+        // check if there was a resolver for OIDC and set as a filter param
+        String keycloakResolverClass = getKeycloakResolverClass(webXmlDoc);
+        if (keycloakResolverClass != null) {
+            Element initParam = webXmlDoc.createElement("init-param");
+            Element paramName = webXmlDoc.createElement("param-name");
+            paramName.setTextContent("keycloak.config.resolver");
+            Element paramValue = webXmlDoc.createElement("param-value");
+            paramValue.setTextContent(keycloakResolverClass);
+            initParam.appendChild(paramName);
+            initParam.appendChild(paramValue);
+            filter.appendChild(initParam);
+        }
+
         // Limitation that all deployments of annotated class use same skipPattern. Refactor if 
         // something more flexible is needed (would require more tricky web.xml parsing though...)
         String skipPattern = testClass.getAnnotation(UseServletFilter.class).skipPattern();
@@ -131,6 +153,23 @@ public class DeploymentArchiveProcessorUtils {
         
         archive.add(new StringAsset((IOUtil.documentToString(webXmlDoc))), WEBXML_PATH);
     }
+    
+    public static String getKeycloakResolverClass(Document doc) {
+        try {
+            XPathFactory factory = XPathFactory.newInstance();
+            XPath xpath = factory.newXPath();
+            XPathExpression expr = xpath.compile("//web-app/context-param[param-name='keycloak.config.resolver']/param-value/text()");
+            NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
+            if (nodes != null && nodes.getLength() > 0) {
+                return nodes.item(0).getNodeValue();
+            }
+        } catch(DOMException e) {
+            throw new IllegalStateException(e);
+        } catch (XPathExpressionException e) {
+            throw new IllegalStateException(e);
+        }
+        return null;
+    }
 
     public static void addFilterDependencies(Archive<?> archive, TestClass testClass) {
         log.info("Adding filter dependencies to " + archive.getName());
@@ -163,8 +202,8 @@ public class DeploymentArchiveProcessorUtils {
         }
     }
 
-    public static void modifySAMLAdapterConfig(Archive<?> archive) {
-        Document doc = IOUtil.loadXML(archive.get(SAML_ADAPTER_CONFIG_PATH).getAsset().openStream());
+    public static void modifySAMLAdapterConfig(Archive<?> archive, String adapterConfigPath) {
+        Document doc = IOUtil.loadXML(archive.get(adapterConfigPath).getAsset().openStream());
 
         if (AUTH_SERVER_SSL_REQUIRED) {
             IOUtil.modifyDocElementAttribute(doc, "SingleSignOnService", "bindingUrl", "8080", System.getProperty("auth.server.https.port"));
@@ -185,7 +224,7 @@ public class DeploymentArchiveProcessorUtils {
             IOUtil.modifyDocElementAttribute(doc, "SP", "logoutPage", "8081", System.getProperty("app.server.http.port"));
         }
 
-        archive.add(new StringAsset(IOUtil.documentToString(doc)), SAML_ADAPTER_CONFIG_PATH);
+        archive.add(new StringAsset(IOUtil.documentToString(doc)), adapterConfigPath);
 
         ((WebArchive) archive).addAsResource(new File(DeploymentArchiveProcessorUtils.class.getResource("/keystore/keycloak.truststore").getFile()));
     }