From 91bcc24977fa47cd6f53bc849dc6f4cf6e58c91b Mon Sep 17 00:00:00 2001 From: mhajas Date: Fri, 10 Feb 2017 15:41:05 +0100 Subject: [PATCH] KEYCLOAK-4329 Add test for empty KeyInfo --- .../org/keycloak/testsuite/util/IOUtil.java | 21 +++++++++ .../AbstractSAMLFilterServletAdapterTest.java | 6 ++- .../AbstractSAMLServletsAdapterTest.java | 44 ++++++++++++++++++- .../keycloak/testsuite/util/SamlClient.java | 39 ++++++++++++++++ .../adapter-test/keycloak-saml/testsaml.json | 1 + 5 files changed, 109 insertions(+), 2 deletions(-) diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java index 5bdea6e992..f11ac070da 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java @@ -227,6 +227,27 @@ public class IOUtil { currentElement.appendChild(node); } + public static void removeElementFromDoc(Document doc, String path) { + String[] pathSegments = path.split("/"); + + Element currentElement = (Element) doc.getElementsByTagName(pathSegments[0]).item(0); + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[0] + " in document"); + return; + } + + for (int i = 1; i < pathSegments.length; i++) { + currentElement = (Element) currentElement.getElementsByTagName(pathSegments[i]).item(0); + + if (currentElement == null) { + log.warn("Not able to find element: " + pathSegments[i] + " in " + pathSegments[i - 1]); + return; + } + } + + currentElement.getParentNode().removeChild(currentElement); + } + public static void execCommand(String command, File dir) throws IOException, InterruptedException { Process process = Runtime.getRuntime().exec(command, null, dir); if (process.waitFor(10, TimeUnit.SECONDS)) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java index ae64a74f24..d89fe67fd0 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java @@ -25,7 +25,6 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS salesPostEncServletPage.checkRoles(true); salesPostSigServletPage.checkRoles(true); salesPostPassiveServletPage.checkRoles(true); - salesPostSigEmailServletPage.checkRoles(true); salesPostSigPersistentServletPage.checkRoles(true); salesPostSigTransientServletPage.checkRoles(true); salesPostAssertionAndResponseSigPage.checkRoles(true); @@ -38,6 +37,11 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS testRealmLoginPage.form().login(bburkeUser); employee2ServletPage.checkRolesEndPoint(true); employee2ServletPage.logout(); + + salesPostSigEmailServletPage.navigateTo(); + testRealmLoginPage.form().login(bburkeUser); + salesPostSigEmailServletPage.checkRolesEndPoint(true); + salesPostSigEmailServletPage.logout(); } @After diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java index e728eaa378..28fd3e16a4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java @@ -130,6 +130,7 @@ import static org.keycloak.testsuite.util.IOUtil.loadXML; import static org.keycloak.testsuite.util.IOUtil.modifyDocElementAttribute; import static org.keycloak.testsuite.util.Matchers.bodyHC; import static org.keycloak.testsuite.util.Matchers.statusCodeIsHC; +import static org.keycloak.testsuite.util.SamlClient.idpInitiatedLogin; import static org.keycloak.testsuite.util.SamlClient.login; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; @@ -734,7 +735,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd } @Test - public void idpInitiatedLogin() { + public void idpInitiatedLoginTest() { samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO); samlidpInitiatedLoginPage.setUrlName("employee2"); samlidpInitiatedLoginPage.navigateTo(); @@ -1027,6 +1028,47 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd } } + // KEYCLOAK-4329 + @Test + public void testEmptyKeyInfoElement() { + samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO); + samlidpInitiatedLoginPage.setUrlName("sales-post-sig-email"); + System.out.println(samlidpInitiatedLoginPage.toString()); + URI idpInitiatedLoginPage = URI.create(samlidpInitiatedLoginPage.toString()); + + log.debug("Log in using idp initiated login"); + SAMLDocumentHolder documentHolder = idpInitiatedLogin(bburkeUser, idpInitiatedLoginPage, SamlClient.Binding.POST); + + + log.debug("Removing KeyInfo from Keycloak response"); + Document responseDoc = documentHolder.getSamlDocument(); + IOUtil.removeElementFromDoc(responseDoc, "samlp:Response/dsig:Signature/dsig:KeyInfo"); + + CloseableHttpResponse response = null; + try (CloseableHttpClient client = HttpClientBuilder.create().build()) { + HttpClientContext context = HttpClientContext.create(); + + log.debug("Sending response to SP"); + HttpUriRequest post = SamlClient.Binding.POST.createSamlPostUnsignedRequest(getAppServerSamlEndpoint(salesPostSigEmailServletPage), null, responseDoc); + response = client.execute(post, context); + System.out.println(EntityUtils.toString(response.getEntity())); + assertThat(response, statusCodeIsHC(Response.Status.FOUND)); + response.close(); + + HttpGet get = new HttpGet(salesPostSigEmailServletPage.toString()); + response = client.execute(get); + assertThat(response, statusCodeIsHC(Response.Status.OK)); + assertThat(response, bodyHC(containsString("principal=bburke"))); + } catch (Exception ex) { + throw new RuntimeException(ex); + } finally { + if (response != null) { + EntityUtils.consumeQuietly(response.getEntity()); + try { response.close(); } catch (IOException ex) { } + } + } + } + private URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException { return RealmsResource .protocolUrl(UriBuilder.fromUri(getAuthServerRoot())) diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SamlClient.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SamlClient.java index f4066f6fcd..8a278964e4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SamlClient.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SamlClient.java @@ -348,4 +348,43 @@ public class SamlClient { } } + /** + * Send request for login form and then login using user param + * @param user + * @param idpInitiatedURI + * @param expectedResponseBinding + * @return + */ + public static SAMLDocumentHolder idpInitiatedLogin(UserRepresentation user, URI idpInitiatedURI, Binding expectedResponseBinding) { + CloseableHttpResponse response = null; + SamlClient.RedirectStrategyWithSwitchableFollowRedirect strategy = new SamlClient.RedirectStrategyWithSwitchableFollowRedirect(); + try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) { + + HttpGet get = new HttpGet(idpInitiatedURI); + response = client.execute(get); + assertThat(response, statusCodeIsHC(Response.Status.OK)); + + HttpClientContext context = HttpClientContext.create(); + + String loginPageText = EntityUtils.toString(response.getEntity(), "UTF-8"); + response.close(); + + assertThat(loginPageText, containsString("login")); + + HttpUriRequest loginRequest = handleLoginPage(user, loginPageText); + + strategy.setRedirectable(false); + response = client.execute(loginRequest, context); + + return expectedResponseBinding.extractResponse(response); + } catch (Exception ex) { + throw new RuntimeException(ex); + } finally { + if (response != null) { + EntityUtils.consumeQuietly(response.getEntity()); + try { response.close(); } catch (IOException ex) { } + } + } + } + } diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json index cca23fc795..6bed985683 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json @@ -259,6 +259,7 @@ "saml.signature.algorithm": "RSA_SHA256", "saml.client.signature": "true", "saml.authnstatement": "true", + "saml_idp_initiated_sso_url_name" : "sales-post-sig-email", "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw==" } },