all tests
This commit is contained in:
parent
1e9c09d23a
commit
35a00b449d
16 changed files with 378 additions and 110 deletions
|
@ -281,7 +281,7 @@ public abstract class SamlAuthenticator {
|
||||||
attributes.add(attr.getName(), value);
|
attributes.add(attr.getName(), value);
|
||||||
}
|
}
|
||||||
if (attr.getFriendlyName() != null) {
|
if (attr.getFriendlyName() != null) {
|
||||||
attributes.add(attr.getFriendlyName(), value);
|
friendlyAttributes.add(attr.getFriendlyName(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,8 @@ public class DeploymentBuilder {
|
||||||
KeyPair keyPair = new KeyPair(publicKey, privateKey);
|
KeyPair keyPair = new KeyPair(publicKey, privateKey);
|
||||||
deployment.setSigningKeyPair(keyPair);
|
deployment.setSigningKeyPair(keyPair);
|
||||||
|
|
||||||
} else if (key.isEncryption()) {
|
}
|
||||||
|
if (key.isEncryption()) {
|
||||||
KeyStore keyStore = loadKeystore(resourceLoader, key);
|
KeyStore keyStore = loadKeystore(resourceLoader, key);
|
||||||
try {
|
try {
|
||||||
PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
|
PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
|
||||||
|
|
|
@ -533,6 +533,9 @@ public class AssertionUtil {
|
||||||
EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
|
EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
|
||||||
|
|
||||||
if (encryptedAssertion != null) {
|
if (encryptedAssertion != null) {
|
||||||
|
if (privateKey == null) {
|
||||||
|
throw new ProcessingException("Encryptd assertion and decrypt private key is null");
|
||||||
|
}
|
||||||
decryptAssertion(responseType, privateKey);
|
decryptAssertion(responseType, privateKey);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,7 @@ import org.junit.ClassRule;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
import org.keycloak.adapters.saml.SamlPrincipal;
|
||||||
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.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.Constants;
|
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.RoleListMapper;
|
||||||
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
|
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
|
||||||
import org.keycloak.representations.AccessToken;
|
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.core.saml.v2.constants.X500SAMLProfileConstants;
|
||||||
import org.keycloak.saml.processing.web.util.PostBindingUtil;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.resources.admin.AdminRoot;
|
import org.keycloak.services.resources.admin.AdminRoot;
|
||||||
import org.keycloak.testsuite.pages.LoginPage;
|
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.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @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-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-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-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("/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/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-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/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);
|
initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc", "post-enc.war", classLoader);
|
||||||
//uploadSP();
|
uploadSP();
|
||||||
server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
|
server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +84,7 @@ public class SamlBindingTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRealmJson() {
|
public String getRealmJson() {
|
||||||
return "/saml/testsaml.json";
|
return "/keycloak-saml/testsaml.json";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,63 +230,35 @@ public class SamlBindingTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAttributes() throws Exception {
|
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;
|
SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
|
||||||
driver.navigate().to("http://localhost:8081/employee/");
|
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
||||||
|
driver.navigate().to("http://localhost:8081/employee2/");
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
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");
|
loginPage.login("bburke", "password");
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
|
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee2/");
|
||||||
Assert.assertNotNull(SamlSPFacade.samlResponse);
|
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
||||||
SAML2Response saml2Response = new SAML2Response();
|
SamlPrincipal principal = (SamlPrincipal)SamlKeycloakRule.SendUsernameServlet.sentPrincipal;
|
||||||
byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
|
Assert.assertNotNull(principal);
|
||||||
ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
|
Assert.assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
|
||||||
Assert.assertTrue(rt.getAssertions().size() == 1);
|
Assert.assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
|
||||||
AssertionType assertion = rt.getAssertions().get(0).getAssertion();
|
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/");
|
||||||
|
|
||||||
// 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.assertTrue(email);
|
|
||||||
Assert.assertTrue(phone);
|
|
||||||
Assert.assertTrue(userRole);
|
|
||||||
Assert.assertTrue(managerRole);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
||||||
@Override
|
@Override
|
||||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
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()) {
|
for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
|
||||||
if (mapper.getName().equals("role-list")) {
|
if (mapper.getName().equals("role-list")) {
|
||||||
app.removeProtocolMapper(mapper);
|
app.removeProtocolMapper(mapper);
|
||||||
|
@ -311,51 +278,25 @@ public class SamlBindingTest {
|
||||||
System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
|
System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
|
||||||
|
|
||||||
{
|
{
|
||||||
SamlSPFacade.samlResponse = null;
|
SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
|
||||||
driver.navigate().to("http://localhost:8081/employee/");
|
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
||||||
System.out.println(driver.getCurrentUrl());
|
driver.navigate().to("http://localhost:8081/employee2/");
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
|
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
||||||
Assert.assertNotNull(SamlSPFacade.samlResponse);
|
List<String> requiredRoles = new LinkedList<>();
|
||||||
SAML2Response saml2Response = new SAML2Response();
|
requiredRoles.add("el-jefe");
|
||||||
byte[] samlResponse = PostBindingUtil.base64Decode(SamlSPFacade.samlResponse);
|
requiredRoles.add("user");
|
||||||
ResponseType rt = saml2Response.getResponseType(new ByteArrayInputStream(samlResponse));
|
requiredRoles.add("hardcoded-role");
|
||||||
Assert.assertTrue(rt.getAssertions().size() == 1);
|
requiredRoles.add("pee-on");
|
||||||
AssertionType assertion = rt.getAssertions().get(0).getAssertion();
|
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"));
|
||||||
|
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
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);
|
Assert.assertNotNull(is);
|
||||||
formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
|
formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import io.undertow.servlet.api.LoginConfig;
|
||||||
import io.undertow.servlet.api.SecurityConstraint;
|
import io.undertow.servlet.api.SecurityConstraint;
|
||||||
import io.undertow.servlet.api.ServletInfo;
|
import io.undertow.servlet.api.ServletInfo;
|
||||||
import io.undertow.servlet.api.WebResourceCollection;
|
import io.undertow.servlet.api.WebResourceCollection;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.keycloak.adapters.saml.undertow.SamlServletExtension;
|
import org.keycloak.adapters.saml.undertow.SamlServletExtension;
|
||||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||||
import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
|
import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
|
||||||
|
@ -24,6 +25,7 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @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 abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
||||||
|
|
||||||
public static class SendUsernameServlet extends HttpServlet {
|
public static class SendUsernameServlet extends HttpServlet {
|
||||||
|
|
||||||
|
public static Principal sentPrincipal;
|
||||||
|
public static List<String> checkRoles;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
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");
|
resp.setContentType("text/plain");
|
||||||
OutputStream stream = resp.getOutputStream();
|
OutputStream stream = resp.getOutputStream();
|
||||||
Principal principal = req.getUserPrincipal();
|
Principal principal = req.getUserPrincipal();
|
||||||
|
@ -47,9 +60,17 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
||||||
}
|
}
|
||||||
String name = principal.getName();
|
String name = principal.getName();
|
||||||
stream.write(name.getBytes());
|
stream.write(name.getBytes());
|
||||||
|
sentPrincipal = principal;
|
||||||
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
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");
|
resp.setContentType("text/plain");
|
||||||
OutputStream stream = resp.getOutputStream();
|
OutputStream stream = resp.getOutputStream();
|
||||||
Principal principal = req.getUserPrincipal();
|
Principal principal = req.getUserPrincipal();
|
||||||
|
@ -63,6 +84,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
||||||
}
|
}
|
||||||
String name = principal.getName();
|
String name = principal.getName();
|
||||||
stream.write(name.getBytes());
|
stream.write(name.getBytes());
|
||||||
|
sentPrincipal = principal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +164,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
||||||
collection.addUrlPattern("/*");
|
collection.addUrlPattern("/*");
|
||||||
constraint.addWebResourceCollection(collection);
|
constraint.addWebResourceCollection(collection);
|
||||||
constraint.addRoleAllowed("manager");
|
constraint.addRoleAllowed("manager");
|
||||||
|
constraint.addRoleAllowed("el-jefe");
|
||||||
LoginConfig loginConfig = new LoginConfig("KEYCLOAK-SAML", "Test Realm");
|
LoginConfig loginConfig = new LoginConfig("KEYCLOAK-SAML", "Test Realm");
|
||||||
|
|
||||||
ResourceManager resourceManager = new TestResourceManager(warResourcePath);
|
ResourceManager resourceManager = new TestResourceManager(warResourcePath);
|
||||||
|
|
|
@ -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>
|
Binary file not shown.
|
@ -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>
|
Binary file not shown.
|
@ -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>
|
Binary file not shown.
|
@ -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>
|
|
@ -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>
|
Binary file not shown.
38
testsuite/integration/src/test/resources/keycloak-saml/sp-metadata.xml
Executable file
38
testsuite/integration/src/test/resources/keycloak-saml/sp-metadata.xml
Executable file
|
@ -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>
|
|
@ -28,7 +28,8 @@
|
||||||
},
|
},
|
||||||
"realmRoles": ["manager", "user"],
|
"realmRoles": ["manager", "user"],
|
||||||
"applicationRoles": {
|
"applicationRoles": {
|
||||||
"http://localhost:8081/employee/": [ "employee" ]
|
"http://localhost:8081/employee/": [ "employee" ],
|
||||||
|
"http://localhost:8081/employee2/": [ "employee" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -219,7 +220,7 @@
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"protocol": "saml",
|
"protocol": "saml",
|
||||||
"fullScopeAllowed": true,
|
"fullScopeAllowed": true,
|
||||||
"baseUrl": "http://localhost:8081/employee",
|
"baseUrl": "http://localhost:8081/employee/",
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:8081/employee/*"
|
"http://localhost:8081/employee/*"
|
||||||
],
|
],
|
||||||
|
@ -264,6 +265,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/",
|
"name": "http://localhost:8081/employee-sig-front/",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -304,6 +355,12 @@
|
||||||
"name": "employee",
|
"name": "employee",
|
||||||
"description": "Have Employee privileges"
|
"description": "Have Employee privileges"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"http://localhost:8081/employee2/" : [
|
||||||
|
{
|
||||||
|
"name": "employee",
|
||||||
|
"description": "Have Employee privileges"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue