[java-plugin-shibd-saml] branch main updated: Fix message handler access to servlet request and add tests.
Scott Cantor
cantor.2 at osu.edu
Thu Oct 3 16:20:40 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-plugin-shibd-saml.
View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd-saml.git;a=commit;h=9b66aa3a8ee6071078e6c7beb654ec8f4a776c57
The following commit(s) were added to refs/heads/main by this push:
new 9b66aa3 Fix message handler access to servlet request and add tests.
9b66aa3 is described below
commit 9b66aa3a8ee6071078e6c7beb654ec8f4a776c57
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Oct 3 12:20:37 2024 -0400
Fix message handler access to servlet request and add tests.
---
.../idp/flows/sp/consumer/saml2/saml2-beans.xml | 3 +-
.../flows/saml2/SAML2TokenConsumerFlowTest.java | 115 +++++++++++++++++++--
2 files changed, 111 insertions(+), 7 deletions(-)
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
index fc243ad..c6dbee6 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-beans.xml
@@ -27,7 +27,8 @@
</constructor-arg>
</bean>
- <bean id="HandleResponse" parent="WebFlowInboundMessageHandlerAdaptor" scope="prototype">
+ <bean id="HandleResponse" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
+ c:executionDirection="INBOUND">
<constructor-arg>
<bean class="org.opensaml.messaging.handler.impl.BasicMessageHandlerChain">
<property name="handlers">
diff --git a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2TokenConsumerFlowTest.java b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2TokenConsumerFlowTest.java
index 97add80..fa785e1 100644
--- a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2TokenConsumerFlowTest.java
+++ b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2TokenConsumerFlowTest.java
@@ -17,6 +17,7 @@ package net.shibboleth.sp.saml.flows.saml2;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.time.Instant;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -26,8 +27,13 @@ import org.opensaml.core.xml.util.XMLObjectSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.saml2.core.Assertion;
+import org.opensaml.saml.saml2.core.AuthnContext;
+import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.core.NameIDType;
import org.opensaml.saml.saml2.core.Response;
import org.opensaml.saml.saml2.core.StatusCode;
+import org.opensaml.saml.saml2.core.Subject;
+import org.opensaml.saml.saml2.core.SubjectConfirmation;
import org.opensaml.saml.saml2.testing.SAML2ActionTestingSupport;
import org.opensaml.security.credential.Credential;
import org.opensaml.storage.StorageService;
@@ -48,6 +54,7 @@ import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.collection.Pair;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.net.URISupport;
+import net.shibboleth.shared.security.IdentifierGenerationStrategy;
import net.shibboleth.sp.context.AgentRequestContext;
import net.shibboleth.sp.ddf.DDF;
import net.shibboleth.sp.flows.AbstractSPFlowTest;
@@ -81,6 +88,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
@Qualifier("shibboleth.StorageService")
protected StorageService storageService;
+ @Autowired
+ @Qualifier("shibboleth.SessionIDGenerator")
+ protected IdentifierGenerationStrategy idGenerator;
+
/** Relay state manager. */
private StorageServiceStateTokenManager stateManager;
@@ -122,6 +133,25 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
}
+ /**
+ * Test flow with error status.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testErrorStatus() throws IOException {
+ setDefaultAuth();
+
+ final Response response = buildSAMLResponse("https://idp.example.org", StatusCode.RESPONDER);
+ final DDF input = buildRemotedPOSTResponse(response);
+ setApplicationRequest(APPLICATION_ID, input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+ }
+
/**
* Test flow with unverified (no metadata) IdP specified.
*
@@ -131,7 +161,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
public void testUnverified() throws IOException {
setDefaultAuth();
- final DDF input = buildRemotedPOSTResponse("https://unknown.example.org", StatusCode.SUCCESS);
+ final DDF input = buildRemotedPOSTResponse(buildSAMLResponse("https://unknown.example.org", StatusCode.SUCCESS));
setApplicationRequest(APPLICATION_ID, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -140,6 +170,46 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
assertOutputMessageEvent(result, IdPEventIds.INVALID_PROFILE_CONFIG);
}
+ /**
+ * Test flow with expired message (the issue instant is old).
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testExpired() throws IOException {
+ setDefaultAuth();
+
+ final Response response = buildSAMLResponse("https://idp.example.org", StatusCode.SUCCESS);
+ response.setIssueInstant(Instant.EPOCH);
+ final DDF input = buildRemotedPOSTResponse(response);
+ setApplicationRequest(APPLICATION_ID, input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+ }
+
+ /**
+ * Test flow with incorrect Destination in response.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void testBadDestination() throws IOException {
+ setDefaultAuth();
+
+ final Response response = buildSAMLResponse("https://idp.example.org", StatusCode.SUCCESS);
+ response.setDestination(RESPONSE_URL + "/bad");
+ final DDF input = buildRemotedPOSTResponse(response);
+ setApplicationRequest(APPLICATION_ID, input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+ }
+
/**
* Decode an encoded response and run sanity checks against it.
*
@@ -165,27 +235,60 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
return output;
}
+
/**
- * Builds a SAML response as encoded into a form POST embedded in a remoted message.
+ * Builds a SAML response with some tailored data.
*
+ * @param issuer issuer value
* @param code status code string
*
* @return input object suitable for token consumer flow
- * @throws IOException
*/
- @Nonnull private DDF buildRemotedPOSTResponse(@Nonnull final String issuer,
- @Nonnull final String code) throws IOException {
+ @Nonnull private Response buildSAMLResponse(@Nonnull final String issuer, @Nonnull final String code) {
final Response response = SAML2ActionTestingSupport.buildResponse();
+ response.setID(idGenerator.generateIdentifier());
+ response.setIssueInstant(Instant.now());
response.setDestination(RESPONSE_URL);
response.setIssuer(SAML2ActionTestingSupport.buildIssuer(issuer));
response.setStatus(SAML2ActionTestingSupport.buildStatus(code, null));
if (StatusCode.SUCCESS.equals(code)) {
final Assertion assertion = SAML2ActionTestingSupport.buildAssertion();
+ assertion.setID(idGenerator.generateIdentifier());
+
+ final Subject subject = SAML2ActionTestingSupport.buildSubject("jdoe at example.org");
+ final NameID nameID = subject.getNameID();
+ assert nameID != null;
+ nameID.setFormat(NameIDType.EMAIL);
+
+ subject.getSubjectConfirmations().add(
+ SAML2ActionTestingSupport.buildSubjectConfirmation(
+ SubjectConfirmation.METHOD_BEARER, RESPONSE_URL, "192.168.1.1"));
+
+ assertion.setSubject(subject);
+
+ assertion.getAuthnStatements().add(
+ SAML2ActionTestingSupport.buildAuthnStatement(
+ Instant.now().minusSeconds(300), "192.168.1.1", AuthnContext.PPT_AUTHN_CTX));
+
response.getAssertions().add(assertion);
}
-
+
+ return response;
+ }
+
+ /**
+ * Encodes a SAML response into a form POST embedded in a remoted message.
+ *
+ * @param response SAML response to encode
+ *
+ * @return input object suitable for token consumer flow
+ *
+ * @throws IOException on error
+ */
+ @Nonnull private DDF buildRemotedPOSTResponse(@Nonnull final Response response) throws IOException {
+
try (final ByteArrayOutputStream sink = new ByteArrayOutputStream()) {
XMLObjectSupport.marshallToOutputStream(response, sink);
final String base64 = Base64Support.encode(sink.toByteArray(), true);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list