keycloak-aplcache
Changes
saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java 3(+2 -1)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java 3(+3 -0)
testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java 153(+47 -106)
testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlKeycloakRule.java 23(+23 -0)
testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keycloak-saml.xml 45(+45 -0)
testsuite/integration/src/test/resources/keycloak-saml/bad-client-signed-post/WEB-INF/keystore.jks 0(+0 -0)
testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keycloak-saml.xml 45(+45 -0)
testsuite/integration/src/test/resources/keycloak-saml/bad-realm-signed-post/WEB-INF/keystore.jks 0(+0 -0)
testsuite/integration/src/test/resources/keycloak-saml/encrypted-post/WEB-INF/keycloak-saml.xml 45(+45 -0)
testsuite/integration/src/test/resources/keycloak-saml/signed-metadata/WEB-INF/keycloak-saml.xml 45(+45 -0)
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"
+ }
]
}
}