KEYCLOAK-4160

This commit is contained in:
mhajas 2017-02-14 11:59:11 +01:00
parent 44c81910bf
commit b1510c43ff
7 changed files with 200 additions and 76 deletions

View file

@ -158,6 +158,22 @@ public class IOUtil {
node.setTextContent(node.getTextContent().replace(regex, replacement)); node.setTextContent(node.getTextContent().replace(regex, replacement));
} }
public static void setDocElementAttributeValue(Document doc, String tagName, String attributeName, String value) {
NodeList nodes = doc.getElementsByTagName(tagName);
if (nodes.getLength() != 1) {
log.warn("Not able or ambiguous to find element: " + tagName);
return;
}
Element node = (Element) nodes.item(0);
if (node == null) {
log.warn("Not able to find element: " + tagName);
return;
}
node.setAttribute(attributeName, value);
}
public static void removeElementsFromDoc(Document doc, String parentTag, String removeNode) { public static void removeElementsFromDoc(Document doc, String parentTag, String removeNode) {
NodeList nodes = doc.getElementsByTagName(parentTag); NodeList nodes = doc.getElementsByTagName(parentTag);
if (nodes.getLength() != 1) { if (nodes.getLength() != 1) {

View file

@ -1009,7 +1009,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
try (CloseableHttpClient client = HttpClientBuilder.create().build()) { try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
HttpClientContext context = HttpClientContext.create(); HttpClientContext context = HttpClientContext.create();
HttpUriRequest post = SamlClient.Binding.POST.createSamlPostUnsignedRequest(getAppServerSamlEndpoint(employee2ServletPage), null, responseDoc); HttpUriRequest post = SamlClient.Binding.POST.createSamlUnsignedResponse(getAppServerSamlEndpoint(employee2ServletPage), null, responseDoc);
response = client.execute(post, context); response = client.execute(post, context);
assertThat(response, statusCodeIsHC(Response.Status.FOUND)); assertThat(response, statusCodeIsHC(Response.Status.FOUND));
response.close(); response.close();
@ -1049,7 +1049,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
HttpClientContext context = HttpClientContext.create(); HttpClientContext context = HttpClientContext.create();
log.debug("Sending response to SP"); log.debug("Sending response to SP");
HttpUriRequest post = SamlClient.Binding.POST.createSamlPostUnsignedRequest(getAppServerSamlEndpoint(salesPostSigEmailServletPage), null, responseDoc); HttpUriRequest post = SamlClient.Binding.POST.createSamlUnsignedResponse(getAppServerSamlEndpoint(salesPostSigEmailServletPage), null, responseDoc);
response = client.execute(post, context); response = client.execute(post, context);
System.out.println(EntityUtils.toString(response.getEntity())); System.out.println(EntityUtils.toString(response.getEntity()));
assertThat(response, statusCodeIsHC(Response.Status.FOUND)); assertThat(response, statusCodeIsHC(Response.Status.FOUND));

View file

@ -21,12 +21,17 @@ import static org.keycloak.testsuite.util.IOUtil.loadRealm;
public class AbstractSamlTest extends AbstractAuthTest { public class AbstractSamlTest extends AbstractAuthTest {
protected static final String REALM_NAME = "demo"; protected static final String REALM_NAME = "demo";
protected static final String REALM_PRIVATE_KEY = "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=";
protected static final String REALM_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB";
protected static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST = "http://localhost:8080/sales-post/"; protected static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST = "http://localhost:8080/sales-post/";
protected static final String SAML_CLIENT_ID_SALES_POST = "http://localhost:8081/sales-post/"; protected static final String SAML_CLIENT_ID_SALES_POST = "http://localhost:8081/sales-post/";
protected static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST_ENC = "http://localhost:8080/sales-post-enc/"; protected static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST_ENC = "http://localhost:8080/sales-post-enc/";
protected static final String SAML_CLIENT_ID_SALES_POST_ENC = "http://localhost:8081/sales-post-enc/"; protected static final String SAML_CLIENT_ID_SALES_POST_ENC = "http://localhost:8081/sales-post-enc/";
protected static final String SAML_CLIENT_SALES_POST_ENC_PRIVATE_KEY = "MIICXQIBAAKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQABAoGBANtbZG9bruoSGp2s5zhzLzd4hczT6Jfk3o9hYjzNb5Z60ymN3Z1omXtQAdEiiNHkRdNxK+EM7TcKBfmoJqcaeTkW8cksVEAW23ip8W9/XsLqmbU2mRrJiKa+KQNDSHqJi1VGyimi4DDApcaqRZcaKDFXg2KDr/Qt5JFD/o9IIIPZAkEA+ZENdBIlpbUfkJh6Ln+bUTss/FZ1FsrcPZWu13rChRMrsmXsfzu9kZUWdUeQ2Dj5AoW2Q7L/cqdGXS7Mm5XhcwJBAOGZq9axJY5YhKrsksvYRLhQbStmGu5LG75suF+rc/44sFq+aQM7+oeRr4VY88Mvz7mk4esdfnk7ae+cCazqJvMCQQCx1L1cZw3yfRSn6S6u8XjQMjWE/WpjulujeoRiwPPY9WcesOgLZZtYIH8nRL6ehEJTnMnahbLmlPFbttxPRUanAkA11MtSIVcKzkhp2KV2ipZrPJWwI18NuVJXb+3WtjypTrGWFZVNNkSjkLnHIeCYlJIGhDd8OL9zAiBXEm6kmgLNAkBWAg0tK2hCjvzsaA505gWQb4X56uKWdb0IzN+fOLB3Qt7+fLqbVQNQoNGzqey6B4MoS1fUKAStqdGTFYPG/+9t";
protected static final String SAML_CLIENT_SALES_POST_ENC_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDb7kwJPkGdU34hicplwfp6/WmNcaLh94TSc7Jyr9Undp5pkyLgb0DE7EIE+6kSs4LsqCb8HDkB0nLD5DXbBJFd8n0WGoKstelvtg6FtVJMnwN7k7yZbfkPECWH9zF70VeOo9vbzrApNRnct8ZhH5fbflRB4JMA9L9R+LbURdoSKQIDAQAB";
@Override @Override
public void addTestRealms(List<RealmRepresentation> testRealms) { public void addTestRealms(List<RealmRepresentation> testRealms) {

View file

@ -0,0 +1,38 @@
package org.keycloak.testsuite.saml;
import org.junit.Test;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.testsuite.util.SamlClient;
import org.w3c.dom.Document;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static org.keycloak.testsuite.util.IOUtil.documentToString;
import static org.keycloak.testsuite.util.IOUtil.setDocElementAttributeValue;
import static org.keycloak.testsuite.util.SamlClient.login;
/**
* @author mhajas
*/
public class BasicSamlTest extends AbstractSamlTest {
// KEYCLOAK-4160
@Test
public void testPropertyValueInAssertion() throws ParsingException, ConfigurationException, ProcessingException {
AuthnRequestType loginRep = createLoginRequestDocument(SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, REALM_NAME);
Document doc = SAML2Request.convert(loginRep);
setDocElementAttributeValue(doc, "samlp:AuthnRequest", "ID", "${java.version}" );
SAMLDocumentHolder document = login(bburkeUser, getAuthServerSamlEndpoint(REALM_NAME), doc, null, SamlClient.Binding.POST, SamlClient.Binding.POST);
assertThat(documentToString(document.getSamlDocument()), not(containsString("InResponseTo=\"" + System.getProperty("java.version") + "\"")));
}
}

View file

@ -17,12 +17,9 @@
package org.keycloak.testsuite.saml; package org.keycloak.testsuite.saml;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType; import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request; import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.testsuite.AbstractAuthTest;
import org.keycloak.testsuite.util.SamlClient; import org.keycloak.testsuite.util.SamlClient;
import java.io.IOException; import java.io.IOException;
@ -33,8 +30,7 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriBuilderException;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.client.protocol.HttpClientContext;
@ -65,7 +61,7 @@ public class ConcurrentAuthnRequestTest extends AbstractSamlTest {
ExecutorService threadPool = Executors.newFixedThreadPool(CONCURRENT_THREADS); ExecutorService threadPool = Executors.newFixedThreadPool(CONCURRENT_THREADS);
try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) { try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) {
HttpUriRequest post = requestBinding.createSamlRequest(samlEndpoint, relayState, samlRequest); HttpUriRequest post = requestBinding.createSamlUnsignedRequest(samlEndpoint, relayState, samlRequest);
Collection<Callable<Void>> futures = new LinkedList<>(); Collection<Callable<Void>> futures = new LinkedList<>();
for (int i = 0; i < ITERATIONS; i ++) { for (int i = 0; i < ITERATIONS; i ++) {

View file

@ -0,0 +1,42 @@
package org.keycloak.testsuite.util;
import org.keycloak.common.util.BouncyIntegration;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* @author mhajas
*/
public class KeyUtils {
static {
BouncyIntegration.init();
}
public static PublicKey publicKeyFromString(String key) {
try {
KeyFactory kf = KeyFactory.getInstance("RSA");
byte[] encoded = Base64.getDecoder().decode(key);
return kf.generatePublic(new X509EncodedKeySpec(encoded));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException(e);
}
}
public static PrivateKey privateKeyFromString(String key) {
try {
KeyFactory kf = KeyFactory.getInstance("RSA");
byte[] encoded = Base64.getDecoder().decode(key);
return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded));
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -16,53 +16,56 @@
*/ */
package org.keycloak.testsuite.util; package org.keycloak.testsuite.util;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.saml.BaseSAML2BindingBuilder;
import org.keycloak.saml.SAMLRequestParser;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy; import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
import org.keycloak.common.util.KeyUtils;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.saml.BaseSAML2BindingBuilder;
import org.keycloak.saml.SAMLRequestParser;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.keycloak.testsuite.admin.Users.getPasswordOf; import static org.keycloak.testsuite.admin.Users.getPasswordOf;
import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.getAuthServerContextRoot; import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.getAuthServerContextRoot;
import static org.keycloak.testsuite.util.Matchers.*; import static org.keycloak.testsuite.util.IOUtil.documentToString;
import static org.keycloak.testsuite.util.Matchers.statusCodeIsHC;
/** /**
*
* @author hmlnarik * @author hmlnarik
*/ */
public class SamlClient { public class SamlClient {
@ -81,45 +84,41 @@ public class SamlClient {
} }
@Override @Override
public HttpPost createSamlRequest(URI samlEndpoint, String relayState, Document samlRequest) { public HttpPost createSamlUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest) {
HttpPost post = new HttpPost(samlEndpoint); return createSamlPostMessage(samlEndpoint, relayState, samlRequest, GeneralConstants.SAML_REQUEST_KEY, null, null);
List<NameValuePair> parameters = new LinkedList<>();
try {
parameters.add(
new BasicNameValuePair(GeneralConstants.SAML_REQUEST_KEY,
new BaseSAML2BindingBuilder()
.postBinding(samlRequest)
.encoded())
);
} catch (ProcessingException | ConfigurationException | IOException ex) {
throw new RuntimeException(ex);
}
if (relayState != null) {
parameters.add(new BasicNameValuePair(GeneralConstants.RELAY_STATE, relayState));
}
UrlEncodedFormEntity formEntity;
try {
formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
post.setEntity(formEntity);
return post;
} }
@Override @Override
public HttpPost createSamlPostUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest) { public HttpPost createSamlUnsignedResponse(URI samlEndpoint, String relayState, Document samlRequest) {
return createSamlPostMessage(samlEndpoint, relayState, samlRequest, GeneralConstants.SAML_RESPONSE_KEY, null, null);
}
@Override
public HttpPost createSamlSignedRequest(URI samlEndpoint, String relayState, Document samlRequest, String realmPrivateKey, String realmPublicKey) {
return createSamlPostMessage(samlEndpoint, relayState, samlRequest, GeneralConstants.SAML_REQUEST_KEY, realmPrivateKey, realmPublicKey);
}
private HttpPost createSamlPostMessage(URI samlEndpoint, String relayState, Document samlRequest, String messageType, String privateKeyStr, String publicKeyStr) {
HttpPost post = new HttpPost(samlEndpoint); HttpPost post = new HttpPost(samlEndpoint);
List<NameValuePair> parameters = new LinkedList<>(); List<NameValuePair> parameters = new LinkedList<>();
try { try {
BaseSAML2BindingBuilder binding = new BaseSAML2BindingBuilder();
if (privateKeyStr != null && publicKeyStr != null) {
PrivateKey privateKey = org.keycloak.testsuite.util.KeyUtils.privateKeyFromString(privateKeyStr);
PublicKey publicKey = org.keycloak.testsuite.util.KeyUtils.publicKeyFromString(publicKeyStr);
binding
.signatureAlgorithm(SignatureAlgorithm.RSA_SHA256)
.signWith(KeyUtils.createKeyId(privateKey), privateKey, publicKey)
.signDocument();
}
parameters.add( parameters.add(
new BasicNameValuePair(GeneralConstants.SAML_RESPONSE_KEY, new BasicNameValuePair(messageType,
new BaseSAML2BindingBuilder() binding
.postBinding(samlRequest) .postBinding(samlRequest)
.encoded()) .encoded())
); );
@ -160,7 +159,7 @@ public class SamlClient {
} }
@Override @Override
public HttpGet createSamlRequest(URI samlEndpoint, String relayState, Document samlRequest) { public HttpGet createSamlUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest) {
try { try {
URI requestURI = new BaseSAML2BindingBuilder() URI requestURI = new BaseSAML2BindingBuilder()
.relayState(relayState) .relayState(relayState)
@ -178,15 +177,25 @@ public class SamlClient {
} }
@Override @Override
public HttpUriRequest createSamlPostUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest) { public HttpUriRequest createSamlUnsignedResponse(URI samlEndpoint, String relayState, Document samlRequest) {
return null;
}
@Override
public HttpUriRequest createSamlSignedRequest(URI samlEndpoint, String relayState, Document samlRequest, String realmPrivateKey, String realmPublicKey) {
return null; return null;
} }
}; };
public abstract SAMLDocumentHolder extractResponse(CloseableHttpResponse response) throws IOException; public abstract SAMLDocumentHolder extractResponse(CloseableHttpResponse response) throws IOException;
public abstract HttpUriRequest createSamlRequest(URI samlEndpoint, String relayState, Document samlRequest);
public abstract HttpUriRequest createSamlUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest);
public abstract HttpUriRequest createSamlSignedRequest(URI samlEndpoint, String relayState, Document samlRequest, String realmPrivateKey, String realmPublicKey);
public abstract URI getBindingUri(); public abstract URI getBindingUri();
public abstract HttpUriRequest createSamlPostUnsignedRequest(URI samlEndpoint, String relayState, Document samlRequest);
public abstract HttpUriRequest createSamlUnsignedResponse(URI samlEndpoint, String relayState, Document samlRequest);
} }
public static class RedirectStrategyWithSwitchableFollowRedirect extends LaxRedirectStrategy { public static class RedirectStrategyWithSwitchableFollowRedirect extends LaxRedirectStrategy {
@ -205,6 +214,7 @@ public class SamlClient {
/** /**
* Extracts and parses value of SAMLResponse input field of a form present in the given page. * Extracts and parses value of SAMLResponse input field of a form present in the given page.
*
* @param responsePage HTML code of the page * @param responsePage HTML code of the page
* @return * @return
*/ */
@ -220,6 +230,7 @@ public class SamlClient {
/** /**
* Extracts and parses value of SAMLResponse query parameter from the given URI. * Extracts and parses value of SAMLResponse query parameter from the given URI.
*
* @param responseUri * @param responseUri
* @return * @return
*/ */
@ -240,6 +251,7 @@ public class SamlClient {
/** /**
* Prepares a GET/POST request for logging the given user into the given login page. The login page is expected * Prepares a GET/POST request for logging the given user into the given login page. The login page is expected
* to have at least input fields with id "username" and "password". * to have at least input fields with id "username" and "password".
*
* @param user * @param user
* @param loginPage * @param loginPage
* @return * @return
@ -292,6 +304,7 @@ public class SamlClient {
/** /**
* Prepares a GET/POST request for consent granting . The consent page is expected * Prepares a GET/POST request for consent granting . The consent page is expected
* to have at least input fields with id "kc-login" and "kc-cancel". * to have at least input fields with id "kc-login" and "kc-cancel".
*
* @param consentPage * @param consentPage
* @param consent * @param consent
* @return * @return
@ -343,6 +356,7 @@ public class SamlClient {
/** /**
* Creates a SAML login request document with the given parameters. See SAML &lt;AuthnRequest&gt; description for more details. * Creates a SAML login request document with the given parameters. See SAML &lt;AuthnRequest&gt; description for more details.
*
* @param issuer * @param issuer
* @param assertionConsumerURL * @param assertionConsumerURL
* @param destination * @param destination
@ -361,6 +375,7 @@ public class SamlClient {
/** /**
* Send request for login form and then login using user param. This method is designed for clients without required consent * Send request for login form and then login using user param. This method is designed for clients without required consent
*
* @param user * @param user
* @param samlEndpoint * @param samlEndpoint
* @param samlRequest * @param samlRequest
@ -376,6 +391,7 @@ public class SamlClient {
/** /**
* Send request for login form and then login using user param. This method is designed for clients which requires consent * Send request for login form and then login using user param. This method is designed for clients which requires consent
*
* @param user * @param user
* @param samlEndpoint * @param samlEndpoint
* @param samlRequest * @param samlRequest
@ -391,6 +407,7 @@ public class SamlClient {
/** /**
* Send request for login form and then login using user param. Check whether client requires consent and handle consent page. * Send request for login form and then login using user param. Check whether client requires consent and handle consent page.
*
* @param user * @param user
* @param samlEndpoint * @param samlEndpoint
* @param samlRequest * @param samlRequest
@ -408,7 +425,7 @@ public class SamlClient {
try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) { try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) {
HttpClientContext context = HttpClientContext.create(); HttpClientContext context = HttpClientContext.create();
HttpUriRequest post = requestBinding.createSamlRequest(samlEndpoint, relayState, samlRequest); HttpUriRequest post = requestBinding.createSamlUnsignedRequest(samlEndpoint, relayState, samlRequest);
response = client.execute(post, context); response = client.execute(post, context);
assertThat(response, statusCodeIsHC(Response.Status.OK)); assertThat(response, statusCodeIsHC(Response.Status.OK));
@ -435,13 +452,17 @@ public class SamlClient {
} finally { } finally {
if (response != null) { if (response != null) {
EntityUtils.consumeQuietly(response.getEntity()); EntityUtils.consumeQuietly(response.getEntity());
try { response.close(); } catch (IOException ex) { } try {
response.close();
} catch (IOException ex) {
}
} }
} }
} }
/** /**
* Send request for login form and then login using user param for clients which doesn't require consent * Send request for login form and then login using user param for clients which doesn't require consent
*
* @param user * @param user
* @param idpInitiatedURI * @param idpInitiatedURI
* @param expectedResponseBinding * @param expectedResponseBinding
@ -453,6 +474,7 @@ public class SamlClient {
/** /**
* Send request for login form and then login using user param. For clients which requires consent * Send request for login form and then login using user param. For clients which requires consent
*
* @param user * @param user
* @param idpInitiatedURI * @param idpInitiatedURI
* @param expectedResponseBinding * @param expectedResponseBinding
@ -465,6 +487,7 @@ public class SamlClient {
/** /**
* Send request for login form and then login using user param. Checks whether client requires consent and handle consent page. * Send request for login form and then login using user param. Checks whether client requires consent and handle consent page.
*
* @param user * @param user
* @param idpInitiatedURI * @param idpInitiatedURI
* @param expectedResponseBinding * @param expectedResponseBinding
@ -505,9 +528,13 @@ public class SamlClient {
} finally { } finally {
if (response != null) { if (response != null) {
EntityUtils.consumeQuietly(response.getEntity()); EntityUtils.consumeQuietly(response.getEntity());
try { response.close(); } catch (IOException ex) { } try {
response.close();
} catch (IOException ex) {
}
} }
} }
} }
} }