keycloak-aplcache

Details

diff --git a/testsuite/integration-arquillian/servers/wildfly/pom.xml b/testsuite/integration-arquillian/servers/wildfly/pom.xml
index 6353c5d..cd3837f 100644
--- a/testsuite/integration-arquillian/servers/wildfly/pom.xml
+++ b/testsuite/integration-arquillian/servers/wildfly/pom.xml
@@ -170,6 +170,11 @@
                     <artifactId>keycloak-wildfly-adapter-dist</artifactId>
                     <type>zip</type>
                 </dependency>
+                <dependency>
+                    <groupId>org.keycloak</groupId>
+                    <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
+                    <type>zip</type>
+                </dependency>
             </dependencies>
             <build>
                 <plugins>
@@ -192,6 +197,13 @@
                                             <type>zip</type>
                                             <outputDirectory>${keycloak.server.home}</outputDirectory>
                                         </artifactItem>
+                                        <artifactItem>
+                                            <groupId>org.keycloak</groupId>
+                                            <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
+                                            <version>${project.version}</version>
+                                            <type>zip</type>
+                                            <outputDirectory>${keycloak.server.home}</outputDirectory>
+                                        </artifactItem>
                                     </artifactItems>
                                 </configuration>
                             </execution>
diff --git a/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/standalone.xsl b/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/standalone.xsl
index a483717..9239d67 100644
--- a/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/standalone.xsl
+++ b/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/standalone.xsl
@@ -16,6 +16,7 @@
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
             <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+            <extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
         </xsl:copy>
     </xsl:template>
 
@@ -23,6 +24,7 @@
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
             <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
+            <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
         </xsl:copy>
     </xsl:template>
 
diff --git a/testsuite/integration-arquillian/tests/adapters/pom.xml b/testsuite/integration-arquillian/tests/adapters/pom.xml
index 759ad6f..2b42494 100644
--- a/testsuite/integration-arquillian/tests/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/adapters/pom.xml
@@ -244,6 +244,24 @@
                                                 <version>${project.version}</version>
                                                 <type>war</type>
                                             </artifactItem>
+                                            <artifactItem>
+                                                <groupId>org.keycloak</groupId>
+                                                <artifactId>saml-post-signatures</artifactId>
+                                                <version>${project.version}</version>
+                                                <type>war</type>
+                                            </artifactItem>
+                                            <artifactItem>
+                                                <groupId>org.keycloak</groupId>
+                                                <artifactId>saml-post-encryption</artifactId>
+                                                <version>${project.version}</version>
+                                                <type>war</type>
+                                            </artifactItem>
+                                            <artifactItem>
+                                                <groupId>org.keycloak</groupId>
+                                                <artifactId>saml-redirect-signatures</artifactId>
+                                                <version>${project.version}</version>
+                                                <type>war</type>
+                                            </artifactItem>
                                         </artifactItems>
                                         <outputDirectory>${examples.home}</outputDirectory>
                                         <overWriteIfNewer>true</overWriteIfNewer>
@@ -264,6 +282,13 @@
                                                 <type>zip</type>
                                                 <includes>**/*realm.json</includes>
                                             </artifactItem>
+                                            <artifactItem>
+                                                <groupId>org.keycloak</groupId>
+                                                <artifactId>keycloak-examples-dist</artifactId>
+                                                <version>${project.version}</version>
+                                                <type>zip</type>
+                                                <includes>**/testsaml.json</includes>
+                                            </artifactItem>
                                         </artifactItems>
                                         <outputDirectory>${examples.home}</outputDirectory>
                                         <overWriteIfNewer>true</overWriteIfNewer>
diff --git a/testsuite/integration-arquillian/tests/adapters/wildfly-relative/pom.xml b/testsuite/integration-arquillian/tests/adapters/wildfly-relative/pom.xml
index 30cf25a..20a43e2 100644
--- a/testsuite/integration-arquillian/tests/adapters/wildfly-relative/pom.xml
+++ b/testsuite/integration-arquillian/tests/adapters/wildfly-relative/pom.xml
@@ -30,6 +30,11 @@
             <artifactId>keycloak-wildfly-adapter-dist</artifactId>
             <type>zip</type>
         </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
+            <type>zip</type>
+        </dependency>
     </dependencies>
     
     <profiles>
@@ -48,7 +53,7 @@
                         <executions>
                             <execution>
                                 <id>unpack-adapter</id>
-                                <phase>generate-resources</phase>
+                                <phase>process-resources</phase>
                                 <goals>
                                     <goal>unpack</goal>
                                 </goals>
@@ -61,12 +66,44 @@
                                             <type>zip</type>
                                             <outputDirectory>${adapter.libs.wildfly}</outputDirectory>
                                         </artifactItem>
+                                        <artifactItem>
+                                            <groupId>org.keycloak</groupId>
+                                            <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
+                                            <version>${project.version}</version>
+                                            <type>zip</type>
+                                            <outputDirectory>${adapter.libs.wildfly}</outputDirectory>
+                                        </artifactItem>
                                     </artifactItems>
                                 </configuration>
                             </execution>
                         </executions>
                     </plugin>
                     <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>xml-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>configure-adapter-subsystem</id>
+                                <phase>process-resources</phase>
+                                <goals>
+                                    <goal>transform</goal>
+                                </goals>
+                                <configuration>
+                                    <transformationSets>
+                                        <transformationSet>
+                                            <dir>${auth.server.container}/standalone/configuration</dir>
+                                            <includes>
+                                                <include>standalone.xml</include>
+                                            </includes>
+                                            <stylesheet>src/main/xslt/standalone.xsl</stylesheet>
+                                            <outputDir>${auth.server.container}/standalone/configuration</outputDir>
+                                        </transformationSet>
+                                    </transformationSets>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
                         <groupId>org.apache.maven.plugins</groupId>
                         <artifactId>maven-surefire-plugin</artifactId>
                         <configuration>
diff --git a/testsuite/integration-arquillian/tests/adapters/wildfly-relative/src/main/xslt/standalone.xsl b/testsuite/integration-arquillian/tests/adapters/wildfly-relative/src/main/xslt/standalone.xsl
index a483717..9239d67 100644
--- a/testsuite/integration-arquillian/tests/adapters/wildfly-relative/src/main/xslt/standalone.xsl
+++ b/testsuite/integration-arquillian/tests/adapters/wildfly-relative/src/main/xslt/standalone.xsl
@@ -16,6 +16,7 @@
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
             <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+            <extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
         </xsl:copy>
     </xsl:template>
 
@@ -23,6 +24,7 @@
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
             <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
+            <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
         </xsl:copy>
     </xsl:template>
 
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 0a965d8..23d08eb 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
@@ -1,9 +1,5 @@
 package org.keycloak.testsuite.arquillian;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
 import org.apache.commons.io.IOUtils;
 import org.apache.tools.ant.DirectoryScanner;
 import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
@@ -14,13 +10,23 @@ import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.keycloak.representations.adapters.config.BaseAdapterConfig;
-import static org.keycloak.testsuite.arquillian.ContainersTestEnricher.*;
 import org.keycloak.testsuite.adapter.AdapterLibsMode;
-import static org.keycloak.testsuite.util.IOUtil.loadJson;;
+import org.keycloak.testsuite.util.IOUtil;
 import org.keycloak.util.JsonSerialization;
+import org.w3c.dom.Document;
+
+import javax.xml.transform.TransformerException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.keycloak.testsuite.arquillian.ContainersTestEnricher.*;
+import static org.keycloak.testsuite.util.IOUtil.*;
+
+;
 
 /**
- *
  * @author tkyjovsk
  */
 public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
@@ -34,6 +40,7 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
     public static final String ADAPTER_CONFIG_PATH_TENANT1 = "/WEB-INF/classes/tenant1-keycloak.json";
     public static final String ADAPTER_CONFIG_PATH_TENANT2 = "/WEB-INF/classes/tenant2-keycloak.json";
     public static final String ADAPTER_CONFIG_PATH_JS = "/keycloak.json";
+    public static final String SAML_ADAPTER_CONFIG_PATH = "/WEB-INF/keycloak-saml.xml";
 
     @Override
     public void process(Archive<?> archive, TestClass testClass) {
@@ -46,7 +53,7 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 //            log.info(testClass.getJavaClass().getSimpleName() + " is not an AdapterTest");
 //        }
     }
-    
+
     public static boolean isAdapterTest(TestClass testClass) {
         return hasAppServerContainerAnnotation(testClass.getJavaClass());
     }
@@ -57,29 +64,47 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
         modifyAdapterConfig(archive, ADAPTER_CONFIG_PATH_TENANT1, relative);
         modifyAdapterConfig(archive, ADAPTER_CONFIG_PATH_TENANT2, relative);
         modifyAdapterConfig(archive, ADAPTER_CONFIG_PATH_JS, relative);
+        modifyAdapterConfig(archive, SAML_ADAPTER_CONFIG_PATH, relative);
     }
 
     protected void modifyAdapterConfig(Archive<?> archive, String adapterConfigPath, boolean relative) {
         if (archive.contains(adapterConfigPath)) {
             log.info("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
-            try {
-                BaseAdapterConfig adapterConfig = loadJson(archive.get(adapterConfigPath)
-                        .getAsset().openStream(), BaseAdapterConfig.class);
+            if (adapterConfigPath.equals(SAML_ADAPTER_CONFIG_PATH)) {
+                log.info("Modyfying saml adapter config in " + archive.getName());
 
-                log.info(" setting " + (relative ? "" : "non-") + "relative auth-server-url");
-                if (relative) {
-                    adapterConfig.setAuthServerUrl("/auth");
-//                ac.setRealmKey(null); // TODO verify if realm key is required for relative scneario
-                } else {
-                    adapterConfig.setAuthServerUrl(getAuthServerContextRootFromSystemProperty() + "/auth");
-                    adapterConfig.setRealmKey(REALM_KEY);
+                Document doc = loadXML(archive.get("WEB-INF/keycloak-saml.xml").getAsset().openStream());
+
+                modifyDocElementAttribute(doc, "SingleSignOnService", "bindingUrl", "8080", System.getProperty("auth.server.http.port", null));
+                modifyDocElementAttribute(doc, "SingleLogoutService", "postBindingUrl", "8080", System.getProperty("auth.server.http.port", null));
+                modifyDocElementAttribute(doc, "SingleLogoutService", "redirectBindingUrl", "8080", System.getProperty("auth.server.http.port", null));
+
+                try {
+                    archive.add(new StringAsset(IOUtil.documentToString(doc)), adapterConfigPath);
+                } catch (TransformerException e) {
+                    log.error("Can't transform document to String");
+                    throw new RuntimeException(e);
                 }
+            } else {
+                try {
+                    BaseAdapterConfig adapterConfig = loadJson(archive.get(adapterConfigPath)
+                            .getAsset().openStream(), BaseAdapterConfig.class);
+
+                    log.info(" setting " + (relative ? "" : "non-") + "relative auth-server-url");
+                    if (relative) {
+                        adapterConfig.setAuthServerUrl("/auth");
+//                ac.setRealmKey(null); // TODO verify if realm key is required for relative scneario
+                    } else {
+                        adapterConfig.setAuthServerUrl(getAuthServerContextRootFromSystemProperty() + "/auth");
+                        adapterConfig.setRealmKey(REALM_KEY);
+                    }
 
-                archive.add(new StringAsset(JsonSerialization.writeValueAsPrettyString(adapterConfig)),
-                        adapterConfigPath);
+                    archive.add(new StringAsset(JsonSerialization.writeValueAsPrettyString(adapterConfig)),
+                            adapterConfigPath);
 
-            } catch (IOException ex) {
-                log.log(Level.FATAL, "Cannot serialize adapter config to JSON.", ex);
+                } catch (IOException ex) {
+                    log.log(Level.FATAL, "Cannot serialize adapter config to JSON.", ex);
+                }
             }
         }
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/AuthRealm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/AuthRealm.java
index f6ba6b4..9d19546 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/AuthRealm.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/AuthRealm.java
@@ -21,6 +21,8 @@ public class AuthRealm extends AuthServer implements PageWithLoginUrl {
     public static final String TEST = "test";
     public static final String DEMO = "demo";
     public static final String EXAMPLE = "example";
+    public static final String SAMLDEMO = "saml-demo";
+    public static final String SAMLSERVLETDEMO = "demo";
 
     public static final String ADMIN = "admin";
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/Login.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/Login.java
index adb5759..e1f549d 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/Login.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/Login.java
@@ -17,13 +17,15 @@
  */
 package org.keycloak.testsuite.auth.page.login;
 
-import javax.ws.rs.core.UriBuilder;
 import org.jboss.arquillian.graphene.page.Page;
 import org.keycloak.testsuite.auth.page.AuthRealm;
-import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 
+import javax.ws.rs.core.UriBuilder;
+
+import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
+
 /**
  *
  * @author Petr Mensik
@@ -35,11 +37,10 @@ public abstract class Login extends AuthRealm {
     public static final String OIDC = "openid-connect";
     public static final String SAML = "saml";
 
-
     @Override
     public UriBuilder createUriBuilder() {
         return super.createUriBuilder()
-                .path("protocol/{" + PROTOCOL + "}/auth");
+                .path("protocol/{" + PROTOCOL + "}" + (getProtocol().equals(OIDC) ? "/auth" : ""));
     }
     
     public void setProtocol(String protocol) {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLLogin.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLLogin.java
new file mode 100644
index 0000000..12946f7
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/SAMLLogin.java
@@ -0,0 +1,10 @@
+package org.keycloak.testsuite.auth.page.login;
+
+/**
+ * @author mhajas
+ */
+public class SAMLLogin extends Login {
+    SAMLLogin() {
+        setProtocol(SAML);
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
index 9ff2bcf..e949784 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
@@ -1,12 +1,21 @@
 package org.keycloak.testsuite.util;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.util.JsonSerialization;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.*;
 
 /**
  *
@@ -40,4 +49,37 @@ public class IOUtil {
         return realm;
     }
 
+    public static Document loadXML(InputStream is) {
+        try {
+            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+            return dBuilder.parse(is);
+        } catch (ParserConfigurationException|SAXException|IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String documentToString(Document newDoc) throws TransformerException {
+        DOMSource domSource = new DOMSource(newDoc);
+        Transformer transformer = TransformerFactory.newInstance().newTransformer();
+        StringWriter sw = new StringWriter();
+        StreamResult sr = new StreamResult(sw);
+        transformer.transform(domSource, sr);
+        return sw.toString();
+    }
+
+    public static void modifyDocElementAttribute(Document doc, String tagName, String attributeName, String regex, String replacement) {
+        NodeList nodes = doc.getElementsByTagName(tagName);
+        if (nodes.getLength() != 1) {
+            System.out.println("Not able to find element: " + tagName);
+            return;
+        }
+
+        Node node = nodes.item(0).getAttributes().getNamedItem(attributeName);
+        if (node == null) {
+            System.out.println("Not able to find attribute " + attributeName + " within element: " + tagName);
+            return;
+        }
+        node.setTextContent(node.getTextContent().replace(regex, replacement));
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java
index 0fb0efe..b6d37a4 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java
@@ -17,21 +17,25 @@
  */
 package org.keycloak.testsuite;
 
-import java.text.MessageFormat;
-import java.util.List;
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Before;
 import org.keycloak.admin.client.resource.RealmResource;
-import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
-import static org.keycloak.testsuite.admin.ApiUtil.*;
-import static org.keycloak.testsuite.admin.Users.setPasswordFor;
 import org.keycloak.testsuite.auth.page.AuthRealm;
-import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
 import org.keycloak.testsuite.auth.page.login.OIDCLogin;
+import org.keycloak.testsuite.auth.page.login.SAMLLogin;
 import org.openqa.selenium.Cookie;
 
+import java.text.MessageFormat;
+import java.util.List;
+
+import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
+import static org.keycloak.testsuite.admin.ApiUtil.assignClientRoles;
+import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
+import static org.keycloak.testsuite.admin.Users.setPasswordFor;
+import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
+
 /**
  *
  * @author tkyjovsk
@@ -43,8 +47,13 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
     @Page
     protected OIDCLogin testRealmLoginPage;
 
+    @Page
+    protected SAMLLogin testRealmSAMLLoginPage;
+
     protected UserRepresentation testUser;
 
+    protected UserRepresentation bburkeUser;
+
     @Override
     public void addTestRealms(List<RealmRepresentation> testRealms) {
         RealmRepresentation testRealmRep = new RealmRepresentation();
@@ -60,6 +69,9 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
         testUser = createUserRepresentation("test", "test@email.test", "test", "user", true);
         setPasswordFor(testUser, PASSWORD);
 
+        bburkeUser = createUserRepresentation("bburke", "bburke@redhat.com", "Bill", "Burke", true);
+        setPasswordFor(bburkeUser, PASSWORD);
+
         deleteAllCookiesForTestRealm();
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
index 73ea7a6..a473a41 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
@@ -1,9 +1,5 @@
 package org.keycloak.testsuite.adapter;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
 import org.apache.commons.io.IOUtils;
 import org.jboss.arquillian.graphene.page.Page;
 import org.jboss.shrinkwrap.api.Archive;
@@ -11,9 +7,14 @@ import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.AbstractAuthTest;
+import org.keycloak.testsuite.adapter.page.AppServerContextRoot;
 import org.keycloak.testsuite.arquillian.ContainersTestEnricher;
 import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
-import org.keycloak.testsuite.adapter.page.AppServerContextRoot;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  *
@@ -45,6 +46,7 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
                 modifyClientRedirectUris(tr, appServerContextRootPage.toString(), "");
                 modifyClientUrls(tr, appServerContextRootPage.toString(), "");
                 modifyClientWebOrigins(tr, "8080", System.getProperty("auth.server.http.port", null));
+                modifySamlMasterURLs(tr, "/", "http://localhost:" + System.getProperty("auth.server.http.port", null) + "/");
             } else {
                 modifyClientRedirectUris(tr, "^(/.*/\\*)", appServerContextRootPage.toString() + "$1");
                 modifyClientUrls(tr, "^(/.*)", appServerContextRootPage.toString() + "$1");
@@ -59,14 +61,16 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
     }
 
     protected void modifyClientRedirectUris(RealmRepresentation realm, String regex, String replacement) {
-        for (ClientRepresentation client : realm.getClients()) {
-            List<String> redirectUris = client.getRedirectUris();
-            if (redirectUris != null) {
-                List<String> newRedirectUris = new ArrayList<>();
-                for (String uri : redirectUris) {
-                    newRedirectUris.add(uri.replaceAll(regex, replacement));
+        if (realm.getClients() != null) {
+            for (ClientRepresentation client : realm.getClients()) {
+                List<String> redirectUris = client.getRedirectUris();
+                if (redirectUris != null) {
+                    List<String> newRedirectUris = new ArrayList<>();
+                    for (String uri : redirectUris) {
+                        newRedirectUris.add(uri.replaceAll(regex, replacement));
+                    }
+                    client.setRedirectUris(newRedirectUris);
                 }
-                client.setRedirectUris(newRedirectUris);
             }
         }
     }
@@ -97,6 +101,20 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
         }
     }
 
+    protected void modifySamlMasterURLs(RealmRepresentation realm, String regex, String replacement) {
+        for (ClientRepresentation client : realm.getClients()) {
+            if (client.getProtocol() != null && client.getProtocol().equals("saml")) {
+                log.info("Modifying master URL of SAML client: " + client.getClientId());
+                String masterUrl = client.getAdminUrl();
+                if (masterUrl == null) {
+                    masterUrl = client.getBaseUrl();
+                }
+                masterUrl = masterUrl.replaceFirst(regex, replacement);
+                client.setAdminUrl(masterUrl);
+            }
+        }
+    }
+
     /**
      * Modifies baseUrl, adminUrl and redirectUris for client based on real
      * deployment url of the app.
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 7dc58c0..c13db8d 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
@@ -1,12 +1,17 @@
 package org.keycloak.testsuite.adapter;
 
-import java.net.URL;
-import java.util.List;
+import org.apache.commons.io.IOUtils;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.keycloak.representations.idm.RealmRepresentation;
-import static org.keycloak.testsuite.util.IOUtil.*;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
 import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
 
 public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
 
@@ -31,6 +36,41 @@ public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
         return deployment;
     }
 
+    protected static WebArchive samlServletDeployment(String name, Class... servletClasses) {
+        return samlServletDeployment(name, "keycloak-saml.xml", servletClasses);
+    }
+
+    protected static WebArchive samlServletDeployment(String name, String adapterConfig ,Class... servletClasses) {
+        String baseSAMLPath = "/adapter-test/keycloak-saml/";
+        String webInfPath = baseSAMLPath + name + "/WEB-INF/";
+
+        URL keycloakSAMLConfig = AbstractServletsAdapterTest.class.getResource(webInfPath + adapterConfig);
+        URL webXML = AbstractServletsAdapterTest.class.getResource(baseSAMLPath + "web.xml");
+
+        WebArchive deployment = ShrinkWrap.create(WebArchive.class, name + ".war")
+                .addClasses(servletClasses)
+                .addAsWebInfResource(keycloakSAMLConfig, "keycloak-saml.xml")
+                .addAsWebInfResource(jbossDeploymentStructure, JBOSS_DEPLOYMENT_STRUCTURE_XML);
+
+        String webXMLContent;
+        try {
+            webXMLContent = IOUtils.toString(webXML.openStream())
+                    .replace("%CONTEXT_PATH%", name);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        deployment.add(new StringAsset(webXMLContent), "/WEB-INF/web.xml");
+
+        URL keystore = AbstractServletsAdapterTest.class.getResource(webInfPath + "keystore.jks");
+        if (keystore != null) {
+            deployment.addAsWebInfResource(keystore, "keystore.jks");
+        }
+
+        addContextXml(deployment, name);
+
+        return deployment;
+    }
+
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(loadRealm("/adapter-test/demorealm.json"));