KEYCLOAK-4329 Add test for empty KeyInfo

This commit is contained in:
mhajas 2017-02-10 15:41:05 +01:00
parent d72b67c460
commit 91bcc24977
5 changed files with 109 additions and 2 deletions

View file

@ -227,6 +227,27 @@ public class IOUtil {
currentElement.appendChild(node); 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 { public static void execCommand(String command, File dir) throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec(command, null, dir); Process process = Runtime.getRuntime().exec(command, null, dir);
if (process.waitFor(10, TimeUnit.SECONDS)) { if (process.waitFor(10, TimeUnit.SECONDS)) {

View file

@ -25,7 +25,6 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS
salesPostEncServletPage.checkRoles(true); salesPostEncServletPage.checkRoles(true);
salesPostSigServletPage.checkRoles(true); salesPostSigServletPage.checkRoles(true);
salesPostPassiveServletPage.checkRoles(true); salesPostPassiveServletPage.checkRoles(true);
salesPostSigEmailServletPage.checkRoles(true);
salesPostSigPersistentServletPage.checkRoles(true); salesPostSigPersistentServletPage.checkRoles(true);
salesPostSigTransientServletPage.checkRoles(true); salesPostSigTransientServletPage.checkRoles(true);
salesPostAssertionAndResponseSigPage.checkRoles(true); salesPostAssertionAndResponseSigPage.checkRoles(true);
@ -38,6 +37,11 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS
testRealmLoginPage.form().login(bburkeUser); testRealmLoginPage.form().login(bburkeUser);
employee2ServletPage.checkRolesEndPoint(true); employee2ServletPage.checkRolesEndPoint(true);
employee2ServletPage.logout(); employee2ServletPage.logout();
salesPostSigEmailServletPage.navigateTo();
testRealmLoginPage.form().login(bburkeUser);
salesPostSigEmailServletPage.checkRolesEndPoint(true);
salesPostSigEmailServletPage.logout();
} }
@After @After

View file

@ -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.IOUtil.modifyDocElementAttribute;
import static org.keycloak.testsuite.util.Matchers.bodyHC; import static org.keycloak.testsuite.util.Matchers.bodyHC;
import static org.keycloak.testsuite.util.Matchers.statusCodeIsHC; 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.SamlClient.login;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
@ -734,7 +735,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
} }
@Test @Test
public void idpInitiatedLogin() { public void idpInitiatedLoginTest() {
samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO); samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO);
samlidpInitiatedLoginPage.setUrlName("employee2"); samlidpInitiatedLoginPage.setUrlName("employee2");
samlidpInitiatedLoginPage.navigateTo(); 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 { private URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException {
return RealmsResource return RealmsResource
.protocolUrl(UriBuilder.fromUri(getAuthServerRoot())) .protocolUrl(UriBuilder.fromUri(getAuthServerRoot()))

View file

@ -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) { }
}
}
}
} }

View file

@ -259,6 +259,7 @@
"saml.signature.algorithm": "RSA_SHA256", "saml.signature.algorithm": "RSA_SHA256",
"saml.client.signature": "true", "saml.client.signature": "true",
"saml.authnstatement": "true", "saml.authnstatement": "true",
"saml_idp_initiated_sso_url_name" : "sales-post-sig-email",
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw==" "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
} }
}, },