keycloak-aplcache

all tests

9/23/2015 9:45:20 PM

Changes

Details

diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
index 46e5b8f..b72cb41 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
@@ -89,7 +89,8 @@ public class DeploymentBuilder {
                     KeyPair keyPair = new KeyPair(publicKey, privateKey);
                     deployment.setSigningKeyPair(keyPair);
 
-                } else if (key.isEncryption()) {
+                }
+                if (key.isEncryption()) {
                     KeyStore keyStore = loadKeystore(resourceLoader, key);
                     try {
                         PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
index 99c8c13..ade3e47 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
@@ -281,7 +281,7 @@ public abstract class SamlAuthenticator {
                                     attributes.add(attr.getName(), value);
                                 }
                                 if (attr.getFriendlyName() != null) {
-                                    attributes.add(attr.getFriendlyName(), value);
+                                    friendlyAttributes.add(attr.getFriendlyName(), value);
                                 }
                             }
                         }
diff --git a/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java b/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java
index eaf7d8c..af4d1ed 100755
--- a/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java
+++ b/saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java
@@ -533,6 +533,9 @@ public class AssertionUtil {
         EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
 
         if (encryptedAssertion != null) {
+            if (privateKey == null) {
+                throw new ProcessingException("Encryptd assertion and decrypt private key is null");
+            }
             decryptAssertion(responseType, privateKey);
 
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
index 429fe81..cb0e521 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
@@ -6,10 +6,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.Config;
-import org.keycloak.dom.saml.v2.assertion.AssertionType;
-import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
-import org.keycloak.dom.saml.v2.assertion.AttributeType;
-import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.adapters.saml.SamlPrincipal;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.Constants;
@@ -26,10 +23,7 @@ import org.keycloak.protocol.saml.mappers.HardcodedRole;
 import org.keycloak.protocol.saml.mappers.RoleListMapper;
 import org.keycloak.protocol.saml.mappers.RoleNameMapper;
 import org.keycloak.representations.AccessToken;
-import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
-import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
 import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
-import org.keycloak.saml.processing.web.util.PostBindingUtil;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.admin.AdminRoot;
 import org.keycloak.testsuite.pages.LoginPage;
@@ -52,9 +46,10 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -73,14 +68,14 @@ public class SamlBindingTest {
             initializeSamlSecuredWar("/keycloak-saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
             initializeSamlSecuredWar("/keycloak-saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
             initializeSamlSecuredWar("/keycloak-saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
             initializeSamlSecuredWar("/keycloak-saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
-            //initializeSamlSecuredWar("/saml/simple-get", "/employee",  "employee.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/mappers", "/employee2",  "employee2.war", classLoader);
             initializeSamlSecuredWar("/keycloak-saml/signed-front-get", "/employee-sig-front",  "employee-sig-front.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig",  "bad-realm-post-sig.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc",  "post-enc.war", classLoader);
-            //uploadSP();
+            initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig",  "bad-realm-post-sig.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc",  "post-enc.war", classLoader);
+            uploadSP();
             server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
 
 
@@ -89,7 +84,7 @@ public class SamlBindingTest {
 
         @Override
         public String getRealmJson() {
-            return "/saml/testsaml.json";
+            return "/keycloak-saml/testsaml.json";
         }
     };
 
@@ -235,63 +230,35 @@ public class SamlBindingTest {
 
     }
 
-
     @Test
     public void testAttributes() throws Exception {
-        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
-        // at the assertions sent.  This is because Picketlink, AFAICT, does not give you any way to get access to
-        // the assertion.
-
         {
-            SamlSPFacade.samlResponse = null;
-            driver.navigate().to("http://localhost:8081/employee/");
+            SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
+            driver.navigate().to("http://localhost:8081/employee2/");
             Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
-            System.out.println(driver.getCurrentUrl());
+            List<String> requiredRoles = new LinkedList<>();
+            requiredRoles.add("manager");
+            requiredRoles.add("employee");
+            requiredRoles.add("user");
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
             loginPage.login("bburke", "password");
-            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
-            Assert.assertNotNull(SamlSPFacade.samlResponse);
-            SAML2Response saml2Response = new SAML2Response();
-            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
-            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
-            Assert.assertTrue(rt.getAssertions().size() == 1);
-            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
-
-            // test attributes and roles
-
-            boolean email = false;
-            boolean phone = false;
-            boolean userRole = false;
-            boolean managerRole = false;
-            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                    AttributeType attr = choice.getAttribute();
-                    if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attr.getFriendlyName())) {
-                        Assert.assertEquals(X500SAMLProfileConstants.EMAIL.get(), attr.getName());
-                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get(), attr.getNameFormat());
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "bburke@redhat.com");
-                        email = true;
-                    } else if (attr.getName().equals("phone")) {
-                        Assert.assertEquals(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_BASIC.get(), attr.getNameFormat());
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "617");
-                        phone = true;
-                    } else if (attr.getName().equals("Role")) {
-                        if (attr.getAttributeValue().get(0).equals("manager")) managerRole = true;
-                        if (attr.getAttributeValue().get(0).equals("user")) userRole = true;
-                    }
-                }
-
-            }
+            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee2/");
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
+            SamlPrincipal principal = (SamlPrincipal)SamlKeycloakRule.SendUsernameServlet.sentPrincipal;
+            Assert.assertNotNull(principal);
+            Assert.assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
+            Assert.assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
+            Assert.assertEquals("617", principal.getAttribute("phone"));
+            Assert.assertNull(principal.getFriendlyAttribute("phone"));
+            driver.navigate().to("http://localhost:8081/employee2/?GLO=true");
+            checkLoggedOut("http://localhost:8081/employee2/");
 
-            Assert.assertTrue(email);
-            Assert.assertTrue(phone);
-            Assert.assertTrue(userRole);
-            Assert.assertTrue(managerRole);
         }
-
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {
             @Override
             public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
-                ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee/");
+                ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee2/");
                 for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
                     if (mapper.getName().equals("role-list")) {
                         app.removeProtocolMapper(mapper);
@@ -311,51 +278,25 @@ public class SamlBindingTest {
         System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
 
         {
-            SamlSPFacade.samlResponse = null;
-            driver.navigate().to("http://localhost:8081/employee/");
-            System.out.println(driver.getCurrentUrl());
-            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
-            Assert.assertNotNull(SamlSPFacade.samlResponse);
-            SAML2Response saml2Response = new SAML2Response();
-            byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
-            ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
-            Assert.assertTrue(rt.getAssertions().size() == 1);
-            AssertionType assertion = rt.getAssertions().get(0).getAssertion();
-
-            // test attributes and roles
-
-            boolean userRole = false;
-            boolean managerRole = false;
-            boolean single = false;
-            boolean hardcodedRole = false;
-            boolean hardcodedAttribute = false;
-            boolean peeOn = false;
-            for (AttributeStatementType statement : assertion.getAttributeStatements()) {
-                for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
-                    AttributeType attr = choice.getAttribute();
-                    if (attr.getName().equals("memberOf")) {
-                        if (single) Assert.fail("too many role attributes");
-                        single = true;
-                        for (Object value : attr.getAttributeValue()) {
-                            if (value.equals("el-jefe")) managerRole = true;
-                            if (value.equals("user")) userRole = true;
-                            if (value.equals("hardcoded-role")) hardcodedRole = true;
-                            if (value.equals("pee-on")) peeOn = true;
-                        }
-                    } else if (attr.getName().equals("hardcoded-attribute")) {
-                        hardcodedAttribute = true;
-                        Assert.assertEquals(attr.getAttributeValue().get(0), "hard");
-                    }
-                }
+            SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
+            driver.navigate().to("http://localhost:8081/employee2/");
+            Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+            List<String> requiredRoles = new LinkedList<>();
+            requiredRoles.add("el-jefe");
+            requiredRoles.add("user");
+            requiredRoles.add("hardcoded-role");
+            requiredRoles.add("pee-on");
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
+            loginPage.login("bburke", "password");
+            Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee2/");
+            SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
+            SamlPrincipal principal = (SamlPrincipal)SamlKeycloakRule.SendUsernameServlet.sentPrincipal;
+            Assert.assertNotNull(principal);
+            Assert.assertEquals("hard", principal.getAttribute("hardcoded-attribute"));
 
-            }
 
-            Assert.assertTrue(single);
-            Assert.assertTrue(hardcodedAttribute);
-            Assert.assertTrue(hardcodedRole);
-            Assert.assertTrue(peeOn);
-            Assert.assertTrue(userRole);
-            Assert.assertTrue(managerRole);
         }
     }
 
@@ -495,7 +436,7 @@ public class SamlBindingTest {
 
 
         MultipartFormDataOutput formData = new MultipartFormDataOutput();
-        InputStream is = SamlBindingTest.class.getResourceAsStream("/saml/sp-metadata.xml");
+        InputStream is = SamlBindingTest.class.getResourceAsStream("/keycloak-saml/sp-metadata.xml");
         Assert.assertNotNull(is);
         formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlKeycloakRule.java
index 17b849f..e7889af 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlKeycloakRule.java
@@ -12,6 +12,7 @@ import io.undertow.servlet.api.LoginConfig;
 import io.undertow.servlet.api.SecurityConstraint;
 import io.undertow.servlet.api.ServletInfo;
 import io.undertow.servlet.api.WebResourceCollection;
+import org.junit.Assert;
 import org.keycloak.adapters.saml.undertow.SamlServletExtension;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
 import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
@@ -24,6 +25,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
 import java.security.Principal;
+import java.util.List;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -32,8 +34,19 @@ import java.security.Principal;
 public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
 
     public static class SendUsernameServlet extends HttpServlet {
+
+        public static Principal sentPrincipal;
+        public static List<String> checkRoles;
+
         @Override
         protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+            if (checkRoles != null) {
+                for (String role : checkRoles) {
+                    System.out.println("check role: " + role);
+                    Assert.assertTrue(req.isUserInRole(role));
+                }
+
+            }
             resp.setContentType("text/plain");
             OutputStream stream = resp.getOutputStream();
             Principal principal = req.getUserPrincipal();
@@ -47,9 +60,17 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
             }
             String name = principal.getName();
             stream.write(name.getBytes());
+            sentPrincipal = principal;
+
         }
         @Override
         protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+            if (checkRoles != null) {
+                for (String role : checkRoles) {
+                    Assert.assertTrue(req.isUserInRole(role));
+                }
+
+            }
             resp.setContentType("text/plain");
             OutputStream stream = resp.getOutputStream();
             Principal principal = req.getUserPrincipal();
@@ -63,6 +84,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
             }
             String name = principal.getName();
             stream.write(name.getBytes());
+            sentPrincipal = principal;
         }
     }
 
@@ -142,6 +164,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
         collection.addUrlPattern("/*");
         constraint.addWebResourceCollection(collection);
         constraint.addRoleAllowed("manager");
+        constraint.addRoleAllowed("el-jefe");
         LoginConfig loginConfig = new LoginConfig("KEYCLOAK-SAML", "Test Realm");
 
         ResourceManager resourceManager = new TestResourceManager(warResourcePath);
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..f5b05df
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/bad-client-sales-post-sig/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8081/bad-client-sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8081/bad-client-sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keystore.jks
new file mode 100755
index 0000000..6a3e3ba
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..2f7c581
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/bad-realm-sales-post-sig/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8081/bad-realm-sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8081/bad-realm-sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keystore.jks
new file mode 100755
index 0000000..215384c
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..c892ec7
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post-enc/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" encryption="true">
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-enc/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true" >
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keystore.jks
new file mode 100755
index 0000000..822162c
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/mappers/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/mappers/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..caaff5c
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/mappers/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,25 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/employee2/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="memberOf"/>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..9a57c85
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-metadata/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/sp-metadata.xml b/testsuite/integration/src/test/resources/keycloak-saml/sp-metadata.xml
new file mode 100755
index 0000000..9b8b899
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/sp-metadata.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntitiesDescriptor Name="urn:mace:shibboleth:testshib:two"
+                    xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+        >
+    <EntityDescriptor entityID="http://localhost:8081/sales-metadata/">
+        <SPSSODescriptor AuthnRequestsSigned="true"
+                protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext">
+            <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+            </NameIDFormat>
+            <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/sales-metadata/"/>
+            <AssertionConsumerService
+                    Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8081/sales-metadata/"
+                    index="1" isDefault="true" />
+            <KeyDescriptor use="signing">
+                <dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+                    <dsig:X509Data>
+                        <dsig:X509Certificate>
+                            MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw==
+                        </dsig:X509Certificate>
+                    </dsig:X509Data>
+                </dsig:KeyInfo>
+            </KeyDescriptor>
+        </SPSSODescriptor>
+        <Organization>
+            <OrganizationName xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+                              xml:lang="en">JBoss</OrganizationName>
+            <OrganizationDisplayName xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+                                     xml:lang="en">JBoss by Red Hat</OrganizationDisplayName>
+            <OrganizationURL xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+                             xml:lang="en">http://localhost:8080/sales-metadata/</OrganizationURL>
+        </Organization>
+        <ContactPerson contactType="technical">
+            <GivenName>The</GivenName>
+            <SurName>Admin</SurName>
+            <EmailAddress>admin@mycompany.com</EmailAddress>
+        </ContactPerson>
+    </EntityDescriptor>
+</EntitiesDescriptor>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json b/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
index c6b682d..5fafa8e 100755
--- a/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
+++ b/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
@@ -28,7 +28,8 @@
             },
             "realmRoles": ["manager", "user"],
             "applicationRoles": {
-                "http://localhost:8081/employee/": [ "employee" ]
+                "http://localhost:8081/employee/": [ "employee" ],
+                "http://localhost:8081/employee2/": [ "employee" ]
             }
         }
     ],
@@ -219,7 +220,7 @@
             "enabled": true,
             "protocol": "saml",
             "fullScopeAllowed": true,
-            "baseUrl": "http://localhost:8081/employee",
+            "baseUrl": "http://localhost:8081/employee/",
             "redirectUris": [
                 "http://localhost:8081/employee/*"
             ],
@@ -265,6 +266,56 @@
             ]
         },
         {
+            "name": "http://localhost:8081/employee2/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/employee2/",
+            "redirectUris": [
+                "http://localhost:8081/employee2/*"
+            ],
+            "adminUrl": "http://localhost:8081/employee2/",
+            "attributes": {
+                "saml.authnstatement": "true"
+            },
+            "protocolMappers": [
+                {
+                    "name": "email",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-property-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "email",
+                        "friendly.name": "email",
+                        "attribute.name": "urn:oid:1.2.840.113549.1.9.1",
+                        "attribute.nameformat": "URI Reference"
+                    }
+                },
+                {
+                    "name": "phone",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-user-attribute-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "user.attribute": "phone",
+                        "attribute.name": "phone",
+                        "attribute.nameformat": "Basic"
+                    }
+                },
+                {
+                    "name": "role-list",
+                    "protocol": "saml",
+                    "protocolMapper": "saml-role-list-mapper",
+                    "consentRequired": false,
+                    "config": {
+                        "attribute.name": "Role",
+                        "attribute.nameformat": "Basic",
+                        "single": "false"
+                    }
+                }
+            ]
+        },
+        {
             "name": "http://localhost:8081/employee-sig-front/",
             "enabled": true,
             "protocol": "saml",
@@ -304,6 +355,12 @@
                     "name": "employee",
                     "description": "Have Employee privileges"
                 }
+            ],
+            "http://localhost:8081/employee2/" : [
+                {
+                    "name": "employee",
+                    "description": "Have Employee privileges"
+                }
             ]
         }
     }