keycloak-memoizeit
Changes
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java 98(+42 -56)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java 20(+13 -7)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AbstractSamlTest.java 45(+45 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AuthnRequestNameIdFormatTest.java 22(+1 -21)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ConcurrentAuthnRequestTest.java 13(+1 -12)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/SamlConsentTest.java 55(+55 -0)
Details
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
index 0e06ee1..b45bf84 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
@@ -118,12 +118,8 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
modifyDocElementAttribute(doc, "SingleLogoutService", "redirectBindingUrl", "8080", System.getProperty("auth.server.http.port"));
}
- try {
- archive.add(new StringAsset(IOUtil.documentToString(doc)), adapterConfigPath);
- } catch (TransformerException e) {
- log.error("Can't transform document to String");
- throw new RuntimeException(e);
- }
+ archive.add(new StringAsset(IOUtil.documentToString(doc)), adapterConfigPath);
+
// For running SAML tests it is necessary to have few dependencies on app-server side.
// Few of them are not in adapter zip so we need to add them manually here
@@ -179,78 +175,68 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
String dependency = testClass.getAnnotation(UseServletFilter.class).filterDependency();
((WebArchive) archive).addAsLibraries(KeycloakDependenciesResolver.resolveDependencies((dependency + ":" + System.getProperty("project.version"))));
- try {
- Document jbossXmlDoc = loadXML(archive.get(JBOSS_DEPLOYMENT_XML_PATH).getAsset().openStream());
- removeNodeByAttributeValue(jbossXmlDoc, "dependencies", "module", "name", "org.keycloak.keycloak-saml-core");
- removeNodeByAttributeValue(jbossXmlDoc, "dependencies", "module", "name", "org.keycloak.keycloak-adapter-spi");
- archive.add(new StringAsset((documentToString(jbossXmlDoc))), JBOSS_DEPLOYMENT_XML_PATH);
- } catch (TransformerException e) {
- log.error("Can't transform document to String");
- throw new RuntimeException(e);
- }
+ Document jbossXmlDoc = loadXML(archive.get(JBOSS_DEPLOYMENT_XML_PATH).getAsset().openStream());
+ removeNodeByAttributeValue(jbossXmlDoc, "dependencies", "module", "name", "org.keycloak.keycloak-saml-core");
+ removeNodeByAttributeValue(jbossXmlDoc, "dependencies", "module", "name", "org.keycloak.keycloak-adapter-spi");
+ archive.add(new StringAsset((documentToString(jbossXmlDoc))), JBOSS_DEPLOYMENT_XML_PATH);
}
protected void modifyWebXml(Archive<?> archive, TestClass testClass) {
- try {
- Document webXmlDoc = loadXML(
- archive.get(WEBXML_PATH).getAsset().openStream());
- if (isTomcatAppServer(testClass.getJavaClass())) {
- modifyDocElementValue(webXmlDoc, "auth-method", "KEYCLOAK", "BASIC");
- }
+ Document webXmlDoc = loadXML(
+ archive.get(WEBXML_PATH).getAsset().openStream());
+ if (isTomcatAppServer(testClass.getJavaClass())) {
+ modifyDocElementValue(webXmlDoc, "auth-method", "KEYCLOAK", "BASIC");
+ }
- if (testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class)) {
+ if (testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class)) {
- addFilterDependencies(archive, testClass);
+ addFilterDependencies(archive, testClass);
- //We need to add filter declaration to web.xml
- log.info("Adding filter to " + testClass.getAnnotation(UseServletFilter.class).filterClass() + " with mapping " + testClass.getAnnotation(UseServletFilter.class).filterPattern() + " for " + archive.getName());
+ //We need to add filter declaration to web.xml
+ log.info("Adding filter to " + testClass.getAnnotation(UseServletFilter.class).filterClass() + " with mapping " + testClass.getAnnotation(UseServletFilter.class).filterPattern() + " for " + archive.getName());
- Element filter = webXmlDoc.createElement("filter");
- Element filterName = webXmlDoc.createElement("filter-name");
- Element filterClass = webXmlDoc.createElement("filter-class");
+ Element filter = webXmlDoc.createElement("filter");
+ Element filterName = webXmlDoc.createElement("filter-name");
+ Element filterClass = webXmlDoc.createElement("filter-class");
- filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
- filterClass.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterClass());
+ filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
+ filterClass.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterClass());
- filter.appendChild(filterName);
- filter.appendChild(filterClass);
- appendChildInDocument(webXmlDoc, "web-app", filter);
+ filter.appendChild(filterName);
+ filter.appendChild(filterClass);
+ appendChildInDocument(webXmlDoc, "web-app", filter);
- Element filterMapping = webXmlDoc.createElement("filter-mapping");
+ Element filterMapping = webXmlDoc.createElement("filter-mapping");
- Element urlPattern = webXmlDoc.createElement("url-pattern");
+ Element urlPattern = webXmlDoc.createElement("url-pattern");
- filterName = webXmlDoc.createElement("filter-name");
+ filterName = webXmlDoc.createElement("filter-name");
- filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
- urlPattern.setTextContent(getElementTextContent(webXmlDoc, "web-app/security-constraint/web-resource-collection/url-pattern"));
+ filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
+ urlPattern.setTextContent(getElementTextContent(webXmlDoc, "web-app/security-constraint/web-resource-collection/url-pattern"));
- filterMapping.appendChild(filterName);
- filterMapping.appendChild(urlPattern);
+ filterMapping.appendChild(filterName);
+ filterMapping.appendChild(urlPattern);
- if (!testClass.getAnnotation(UseServletFilter.class).dispatcherType().isEmpty()) {
- Element dispatcher = webXmlDoc.createElement("dispatcher");
- dispatcher.setTextContent(testClass.getAnnotation(UseServletFilter.class).dispatcherType());
- filterMapping.appendChild(dispatcher);
- }
- appendChildInDocument(webXmlDoc, "web-app", filterMapping);
+ if (!testClass.getAnnotation(UseServletFilter.class).dispatcherType().isEmpty()) {
+ Element dispatcher = webXmlDoc.createElement("dispatcher");
+ dispatcher.setTextContent(testClass.getAnnotation(UseServletFilter.class).dispatcherType());
+ filterMapping.appendChild(dispatcher);
+ }
+ appendChildInDocument(webXmlDoc, "web-app", filterMapping);
- //finally we need to remove all keycloak related configuration from web.xml
- removeElementsFromDoc(webXmlDoc, "web-app", "security-constraint");
- removeElementsFromDoc(webXmlDoc, "web-app", "login-config");
- removeElementsFromDoc(webXmlDoc, "web-app", "security-role");
+ //finally we need to remove all keycloak related configuration from web.xml
+ removeElementsFromDoc(webXmlDoc, "web-app", "security-constraint");
+ removeElementsFromDoc(webXmlDoc, "web-app", "login-config");
+ removeElementsFromDoc(webXmlDoc, "web-app", "security-role");
- }
+ }
- archive.add(new StringAsset((documentToString(webXmlDoc))), WEBXML_PATH);
- } catch (TransformerException e) {
- log.error("Can't transform document to String");
- throw new RuntimeException(e);
- }
+ archive.add(new StringAsset((documentToString(webXmlDoc))), WEBXML_PATH);
}
}
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 f11ac07..ea92813 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
@@ -29,6 +29,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
@@ -89,13 +90,18 @@ public class IOUtil {
}
}
- public static String documentToString(Document newDoc) throws TransformerException {
- DOMSource domSource = new DOMSource(newDoc);
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- StringWriter sw = new StringWriter();
- StreamResult sr = new StreamResult(sw);
- transformer.transform(domSource, sr);
- return sw.toString();
+ public static String documentToString(Document newDoc) {
+ try {
+ DOMSource domSource = new DOMSource(newDoc);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ StringWriter sw = new StringWriter();
+ StreamResult sr = new StreamResult(sw);
+ transformer.transform(domSource, sr);
+ return sw.toString();
+ } catch (TransformerException e) {
+ log.error("Can't transform document to String");
+ throw new RuntimeException(e);
+ }
}
public static void modifyDocElementAttribute(Document doc, String tagName, String attributeName, String regex, String replacement) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AbstractSamlTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AbstractSamlTest.java
new file mode 100644
index 0000000..016aa05
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AbstractSamlTest.java
@@ -0,0 +1,45 @@
+package org.keycloak.testsuite.saml;
+
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.protocol.saml.SamlProtocol;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.testsuite.AbstractAuthTest;
+import org.keycloak.testsuite.adapter.page.SAMLServlet;
+import org.keycloak.testsuite.util.SamlClient;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriBuilderException;
+import java.net.URI;
+import java.util.List;
+
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
+
+/**
+ * @author mhajas
+ */
+public class AbstractSamlTest extends AbstractAuthTest {
+
+ protected static final String REALM_NAME = "demo";
+
+ 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_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/";
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ testRealms.add(loadRealm("/adapter-test/keycloak-saml/testsaml.json"));
+ }
+
+ protected AuthnRequestType createLoginRequestDocument(String issuer, String assertionConsumerURL, String realmName) {
+ return SamlClient.createLoginRequestDocument(issuer, assertionConsumerURL, getAuthServerSamlEndpoint(realmName));
+ }
+
+ protected URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException {
+ return RealmsResource
+ .protocolUrl(UriBuilder.fromUri(getAuthServerRoot()))
+ .build(realm, SamlProtocol.LOGIN_PROTOCOL);
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AuthnRequestNameIdFormatTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AuthnRequestNameIdFormatTest.java
index 3bf08c9..4f94260 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AuthnRequestNameIdFormatTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/AuthnRequestNameIdFormatTest.java
@@ -60,27 +60,7 @@ import static org.keycloak.testsuite.util.Matchers.statusCodeIsHC;
*
* @author hmlnarik
*/
-public class AuthnRequestNameIdFormatTest extends AbstractAuthTest {
-
- private static final String REALM_NAME = "demo";
-
- private static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST = "http://localhost:8080/sales-post/";
- private static final String SAML_CLIENT_ID_SALES_POST = "http://localhost:8081/sales-post/";
-
- @Override
- public void addTestRealms(List<RealmRepresentation> testRealms) {
- testRealms.add(loadRealm("/adapter-test/keycloak-saml/testsaml.json"));
- }
-
- public AuthnRequestType createLoginRequestDocument(String issuer, String assertionConsumerURL, String realmName) {
- return SamlClient.createLoginRequestDocument(issuer, assertionConsumerURL, getAuthServerSamlEndpoint(realmName));
- }
-
- private URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException {
- return RealmsResource
- .protocolUrl(UriBuilder.fromUri(getAuthServerRoot()))
- .build(realm, SamlProtocol.LOGIN_PROTOCOL);
- }
+public class AuthnRequestNameIdFormatTest extends AbstractSamlTest {
private void testLoginWithNameIdPolicy(Binding requestBinding, Binding responseBinding, NameIDPolicyType nameIDPolicy, Matcher<String> nameIdMatcher) throws Exception {
AuthnRequestType loginRep = createLoginRequestDocument(SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, REALM_NAME);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ConcurrentAuthnRequestTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ConcurrentAuthnRequestTest.java
index b207c04..03980ef 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ConcurrentAuthnRequestTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/ConcurrentAuthnRequestTest.java
@@ -53,12 +53,7 @@ import static org.keycloak.testsuite.util.IOUtil.loadRealm;
* @author hmlnarik
*/
@Ignore
-public class ConcurrentAuthnRequestTest extends AbstractAuthTest {
-
- private static final String REALM_NAME = "demo";
-
- private static final String SAML_ASSERTION_CONSUMER_URL_SALES_POST = "http://localhost:8080/sales-post/";
- private static final String SAML_CLIENT_ID_SALES_POST = "http://localhost:8081/sales-post/";
+public class ConcurrentAuthnRequestTest extends AbstractSamlTest {
public static final int ITERATIONS = 10000;
public static final int CONCURRENT_THREADS = 5;
@@ -123,12 +118,6 @@ public class ConcurrentAuthnRequestTest extends AbstractAuthTest {
return SamlClient.createLoginRequestDocument(issuer, assertionConsumerURL, getAuthServerSamlEndpoint(realmName));
}
- private URI getAuthServerSamlEndpoint(String realm) throws IllegalArgumentException, UriBuilderException {
- return RealmsResource
- .protocolUrl(UriBuilder.fromUri(getAuthServerRoot()))
- .build(realm, SamlProtocol.LOGIN_PROTOCOL);
- }
-
private void testLogin(Binding requestBinding) throws Exception {
AuthnRequestType loginRep = createLoginRequestDocument(SAML_CLIENT_ID_SALES_POST, SAML_ASSERTION_CONSUMER_URL_SALES_POST, REALM_NAME);
Document samlRequest = SAML2Request.convert(loginRep);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/SamlConsentTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/SamlConsentTest.java
new file mode 100644
index 0000000..1428ac1
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/SamlConsentTest.java
@@ -0,0 +1,55 @@
+package org.keycloak.testsuite.saml;
+
+import org.junit.Test;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+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.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.testsuite.util.ClientBuilder;
+import org.keycloak.testsuite.util.IOUtil;
+import org.keycloak.testsuite.util.SamlClient;
+
+import java.net.URI;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
+import static org.keycloak.testsuite.util.SamlClient.idpInitiatedLoginWithRequiredConsent;
+
+/**
+ * @author mhajas
+ */
+public class SamlConsentTest extends AbstractSamlTest {
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ testRealms.add(loadRealm("/adapter-test/keycloak-saml/testsaml.json"));
+ }
+
+ @Test
+ public void signingOfRejectedConsentAssertionTest() throws ParsingException, ConfigurationException, ProcessingException {
+ ClientRepresentation client = adminClient.realm(REALM_NAME)
+ .clients()
+ .findByClientId(SAML_CLIENT_ID_SALES_POST_ENC)
+ .get(0);
+
+ adminClient.realm(REALM_NAME)
+ .clients()
+ .get(client.getId())
+ .update(ClientBuilder.edit(client)
+ .consentRequired(true)
+ .attribute("saml.encrypt", "false") //remove after RHSSO-797
+ .attribute("saml_idp_initiated_sso_url_name", "sales-post-enc")
+ .attribute("saml_assertion_consumer_url_post", SAML_ASSERTION_CONSUMER_URL_SALES_POST_ENC + "saml")
+ .build());
+
+ log.debug("Log in using idp initiated login");
+ String idpInitiatedLogin = getAuthServerRoot() + "realms/" + REALM_NAME + "/protocol/saml/clients/sales-post-enc";
+ SAMLDocumentHolder documentHolder = idpInitiatedLoginWithRequiredConsent(bburkeUser, URI.create(idpInitiatedLogin), SamlClient.Binding.POST, false);
+
+ assertThat(IOUtil.documentToString(documentHolder.getSamlDocument()), containsString("<dsig:Signature"));
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
index 12fe4a1..7530275 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
@@ -106,7 +106,10 @@ public class ClientBuilder {
}
public ClientBuilder attribute(String name, String value) {
- Map<String, String> attributes = new HashMap<String, String>();
+ Map<String, String> attributes = rep.getAttributes();
+ if (attributes == null) {
+ attributes = new HashMap<>();
+ }
attributes.put(name, value);
rep.setAttributes(attributes);
return this;
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 8a27896..9eae9a1 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
@@ -58,6 +58,7 @@ import org.w3c.dom.Document;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.keycloak.testsuite.admin.Users.getPasswordOf;
+import static org.keycloak.testsuite.arquillian.AuthServerTestEnricher.getAuthServerContextRoot;
import static org.keycloak.testsuite.util.Matchers.*;
/**
@@ -289,6 +290,58 @@ public class SamlClient {
}
/**
+ * 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".
+ * @param consentPage
+ * @param consent
+ * @return
+ */
+ public static HttpUriRequest handleConsentPage(String consentPage, boolean consent) {
+ org.jsoup.nodes.Document theLoginPage = Jsoup.parse(consentPage);
+
+ List<NameValuePair> parameters = new LinkedList<>();
+ for (Element form : theLoginPage.getElementsByTag("form")) {
+ String method = form.attr("method");
+ String action = form.attr("action");
+ boolean isPost = method != null && "post".equalsIgnoreCase(method);
+
+ for (Element input : form.getElementsByTag("input")) {
+ if (Objects.equals(input.id(), "kc-login")) {
+ if (consent)
+ parameters.add(new BasicNameValuePair(input.attr("name"), input.attr("value")));
+ } else if (Objects.equals(input.id(), "kc-cancel")) {
+ if (!consent)
+ parameters.add(new BasicNameValuePair(input.attr("name"), input.attr("value")));
+ } else {
+ parameters.add(new BasicNameValuePair(input.attr("name"), input.val()));
+ }
+ }
+
+ if (isPost) {
+ HttpPost res = new HttpPost(getAuthServerContextRoot() + action);
+
+ UrlEncodedFormEntity formEntity;
+ try {
+ formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ res.setEntity(formEntity);
+
+ return res;
+ } else {
+ UriBuilder b = UriBuilder.fromPath(action);
+ for (NameValuePair parameter : parameters) {
+ b.queryParam(parameter.getName(), parameter.getValue());
+ }
+ return new HttpGet(b.build());
+ }
+ }
+
+ throw new IllegalArgumentException("Invalid consent page: " + consentPage);
+ }
+
+ /**
* Creates a SAML login request document with the given parameters. See SAML <AuthnRequest> description for more details.
* @param issuer
* @param assertionConsumerURL
@@ -307,7 +360,7 @@ public class SamlClient {
}
/**
- * Send request for login form and then login using user param
+ * Send request for login form and then login using user param. This method is designed for clients without required consent
* @param user
* @param samlEndpoint
* @param samlRequest
@@ -318,6 +371,38 @@ public class SamlClient {
*/
public static SAMLDocumentHolder login(UserRepresentation user, URI samlEndpoint,
Document samlRequest, String relayState, Binding requestBinding, Binding expectedResponseBinding) {
+ return login(user, samlEndpoint, samlRequest, relayState, requestBinding, expectedResponseBinding, false, true);
+ }
+
+ /**
+ * Send request for login form and then login using user param. This method is designed for clients which requires consent
+ * @param user
+ * @param samlEndpoint
+ * @param samlRequest
+ * @param relayState
+ * @param requestBinding
+ * @param expectedResponseBinding
+ * @return
+ */
+ public static SAMLDocumentHolder loginWithRequiredConsent(UserRepresentation user, URI samlEndpoint,
+ Document samlRequest, String relayState, Binding requestBinding, Binding expectedResponseBinding, boolean consent) {
+ return login(user, samlEndpoint, samlRequest, relayState, requestBinding, expectedResponseBinding, true, consent);
+ }
+
+ /**
+ * Send request for login form and then login using user param. Check whether client requires consent and handle consent page.
+ * @param user
+ * @param samlEndpoint
+ * @param samlRequest
+ * @param relayState
+ * @param requestBinding
+ * @param expectedResponseBinding
+ * @param consentRequired
+ * @param consent
+ * @return
+ */
+ public static SAMLDocumentHolder login(UserRepresentation user, URI samlEndpoint,
+ Document samlRequest, String relayState, Binding requestBinding, Binding expectedResponseBinding, boolean consentRequired, boolean consent) {
CloseableHttpResponse response = null;
SamlClient.RedirectStrategyWithSwitchableFollowRedirect strategy = new SamlClient.RedirectStrategyWithSwitchableFollowRedirect();
try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) {
@@ -334,6 +419,13 @@ public class SamlClient {
HttpUriRequest loginRequest = handleLoginPage(user, loginPageText);
+ if (consentRequired) {
+ // Client requires consent
+ response = client.execute(loginRequest, context);
+ String consentPageText = EntityUtils.toString(response.getEntity(), "UTF-8");
+ loginRequest = handleConsentPage(consentPageText, consent);
+ }
+
strategy.setRedirectable(false);
response = client.execute(loginRequest, context);
@@ -349,13 +441,37 @@ public class SamlClient {
}
/**
- * Send request for login form and then login using user param
+ * Send request for login form and then login using user param for clients which doesn't require consent
* @param user
* @param idpInitiatedURI
* @param expectedResponseBinding
* @return
*/
public static SAMLDocumentHolder idpInitiatedLogin(UserRepresentation user, URI idpInitiatedURI, Binding expectedResponseBinding) {
+ return idpInitiatedLogin(user, idpInitiatedURI, expectedResponseBinding, false, true);
+ }
+
+ /**
+ * Send request for login form and then login using user param. For clients which requires consent
+ * @param user
+ * @param idpInitiatedURI
+ * @param expectedResponseBinding
+ * @param consent
+ * @return
+ */
+ public static SAMLDocumentHolder idpInitiatedLoginWithRequiredConsent(UserRepresentation user, URI idpInitiatedURI, Binding expectedResponseBinding, boolean consent) {
+ return idpInitiatedLogin(user, idpInitiatedURI, expectedResponseBinding, true, consent);
+ }
+
+ /**
+ * Send request for login form and then login using user param. Checks whether client requires consent and handle consent page.
+ * @param user
+ * @param idpInitiatedURI
+ * @param expectedResponseBinding
+ * @param consent
+ * @return
+ */
+ public static SAMLDocumentHolder idpInitiatedLogin(UserRepresentation user, URI idpInitiatedURI, Binding expectedResponseBinding, boolean consentRequired, boolean consent) {
CloseableHttpResponse response = null;
SamlClient.RedirectStrategyWithSwitchableFollowRedirect strategy = new SamlClient.RedirectStrategyWithSwitchableFollowRedirect();
try (CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(strategy).build()) {
@@ -373,6 +489,13 @@ public class SamlClient {
HttpUriRequest loginRequest = handleLoginPage(user, loginPageText);
+ if (consentRequired) {
+ // Client requires consent
+ response = client.execute(loginRequest, context);
+ String consentPageText = EntityUtils.toString(response.getEntity(), "UTF-8");
+ loginRequest = handleConsentPage(consentPageText, consent);
+ }
+
strategy.setRedirectable(false);
response = client.execute(loginRequest, context);