[java-plugin-shibd-saml] branch dev/StateMgmtWIP updated: Test cleanup, add some additional InResponseTo tests.

Codeberg noreply at shibboleth.net
Wed Apr 29 16:36:30 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch dev/StateMgmtWIP
in repository java-plugin-shibd-saml.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd-saml/commit/fc7e876dd2de33f4a999d1e80430f477a535ffda

The following commit(s) were added to refs/heads/dev/StateMgmtWIP by this push:
     new fc7e876  Test cleanup, add some additional InResponseTo tests.
fc7e876 is described below

commit fc7e876dd2de33f4a999d1e80430f477a535ffda
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Wed Apr 29 12:36:20 2026 -0400

    Test cleanup, add some additional InResponseTo tests.
---
 .../flows/saml2/SAML2TokenConsumerFlowTest.java    | 286 +++++++++++----------
 1 file changed, 147 insertions(+), 139 deletions(-)

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 61aca70..8005296 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
@@ -159,6 +159,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     
     private CookieManager cookieManager;
     private CookieStateManager stateManager;
+    // Renamed to avoid stomping on base class objects.
     private MockHttpServletRequest request2;
     private MockHttpServletResponse response2;
     
@@ -235,10 +236,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     public void testNoInput() throws IOException {
         setApplicationRequest(APPLICATION_ID, null);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
+        validateError(AuthnEventIds.NO_POTENTIAL_FLOW, null);
     }
     
     /**
@@ -250,13 +248,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     public void testErrorStatus() throws IOException {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.RESPONDER, null);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         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);
+        validateError(EventIds.INVALID_MESSAGE, null);
     }
     
     /**
@@ -266,13 +261,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
      */
     @Test
     public void testUnverified() throws IOException {
-        final DDF input = buildRemotedPOSTResponse(buildSAMLResponse(ISSUER + "/bad", StatusCode.SUCCESS, null), null);
+        final DDF input = buildRemotedPOSTResponse(buildSAMLResponse(ISSUER + "/bad", StatusCode.SUCCESS, null), null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        assertOutputMessageEvent(result, IdPEventIds.INVALID_PROFILE_CONFIG);
+        validateError(IdPEventIds.INVALID_PROFILE_CONFIG, null);
     }
     
     /**
@@ -285,13 +277,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         response.setIssueInstant(Instant.EPOCH);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         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);
+        validateError(EventIds.INVALID_MESSAGE, null);
     }
 
     /**
@@ -304,15 +293,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         response.setDestination(RESPONSE_URL + "/bad");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         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);
+        validateError(EventIds.INVALID_MESSAGE, null);
     }
-
+    
     /**
      * Test flow with expired assertion issue instant.
      * 
@@ -323,14 +309,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         response.getAssertions().get(0).setIssueInstant(Instant.now().minusSeconds(1800));
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, "Assertion IssueInstant was expired");
+        validateError(EventIds.INVALID_MESSAGE, "Assertion IssueInstant was expired");
     }
 
     /**
@@ -345,15 +327,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert locality != null;
         locality.setAddress("127.0.0.1");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("SubjectLocality/@Address for assertion '%s' did not match supplied valid addresses: [/192.168.1.1]",
-                response.getAssertions().get(0).getID()));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectLocality/@Address for assertion '%s' did not match supplied valid addresses: [/192.168.1.1]",
+                        response.getAssertions().get(0).getID()));
     }
 
     /**
@@ -370,19 +349,16 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert data != null;
         data.setAddress("127.0.0.1");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("SubjectConfirmationData/@Address for assertion '%s' did not match supplied valid addresses: [/192.168.1.1]",
-                response.getAssertions().get(0).getID()));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@Address for assertion '%s' did not match supplied valid addresses: [/192.168.1.1]",
+                        response.getAssertions().get(0).getID()));
     }
 
     /**
-     * Test flow with bad confirmation address.
+     * Test flow with bad confirmation method.
      * 
      * @throws IOException 
      */
@@ -393,15 +369,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert subject != null;
         subject.getSubjectConfirmations().get(0).setMethod(SubjectConfirmation.METHOD_SENDER_VOUCHES);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("No subject confirmation methods were met for assertion with ID '%s'",
-                response.getAssertions().get(0).getID()));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("No subject confirmation methods were met for assertion with ID '%s'",
+                        response.getAssertions().get(0).getID()));
     }
 
     /**
@@ -418,15 +391,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert data != null;
         data.setNotOnOrAfter(null);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("SubjectConfirmationData/@NotOnOrAfter was missing and was required",
-                response.getAssertions().get(0).getID(), RESPONSE_URL));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@NotOnOrAfter was missing and was required",
+                        response.getAssertions().get(0).getID(), RESPONSE_URL));
     }
     
     /**
@@ -443,15 +413,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert data != null;
         data.setRecipient(null);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("SubjectConfirmationData/@Recipient was missing and was required",
-                response.getAssertions().get(0).getID(), RESPONSE_URL));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@Recipient was missing and was required",
+                        response.getAssertions().get(0).getID(), RESPONSE_URL));
     }
     
     /**
@@ -468,16 +435,30 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert data != null;
         data.setRecipient(RESPONSE_URL + "/bad");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("SubjectConfirmationData/@Recipient for assertion '%s' did not match any valid recipients: [%s]",
-                response.getAssertions().get(0).getID(), RESPONSE_URL));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@Recipient for assertion '%s' did not match any valid recipients: [%s]",
+                        response.getAssertions().get(0).getID(), RESPONSE_URL));
     }
+    
+    /**
+     * Test flow with bad confirmation InResponseTo (no state supplied).
+     * 
+     * @throws IOException 
+     */
+    @Test
+    public void testBadInResponseTo() throws IOException {
+        final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, "bad");
+        sign(response);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
+        setApplicationRequest(APPLICATION_ID, input);
+
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@InResponseTo for assertion '%s' did not match the valid value: null",
+                        response.getAssertions().get(0).getID()));
+    }    
 
     /**
      * Test flow with bad issuer value.
@@ -489,14 +470,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         response.getAssertions().get(0).setIssuer(SAML2ActionTestingSupport.buildIssuer(ISSUER + "bad"));
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output,
+        validateError(EventIds.INVALID_MESSAGE,
                 String.format("Issuer of Assertion '%s' did not match any valid issuers",
                         response.getAssertions().get(0).getID()));
     }
@@ -513,14 +490,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         issuer.setFormat(NameIDType.EMAIL);
         response.getAssertions().get(0).setIssuer(issuer);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, "Issuer had invalid Format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
+        validateError(EventIds.INVALID_MESSAGE, "Issuer had invalid Format: urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
     }
 
     /**
@@ -531,14 +504,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     @Test
     public void testUnsigned() throws IOException {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, "Assertion was required to be signed, but was not");
+        validateError(EventIds.INVALID_MESSAGE, "Assertion was required to be signed, but was not");
     }
 
     /**
@@ -551,14 +520,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         response.getAssertions().get(0).setConditions(null);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, "At least 1 Condition was indicated as required");
+        validateError(EventIds.INVALID_MESSAGE, "At least 1 Condition was indicated as required");
     }
 
     /**
@@ -573,15 +538,11 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert conditions != null;
         conditions.setNotOnOrAfter(Instant.now().minusSeconds(300));
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("Assertion '%s' with NotOnOrAfter condition",
-                response.getAssertions().get(0).getID()));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("Assertion '%s' with NotOnOrAfter condition", response.getAssertions().get(0).getID()));
     }
 
     /**
@@ -596,17 +557,38 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         assert conditions != null;
         conditions.getAudienceRestrictions().get(0).getAudiences().get(0).setURI(AUDIENCE + "/bad");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
-        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
-        assertFlowExecutionResult(result, FLOW_ID);
-        assertFlowExecutionOutcome(result.getOutcome());
-        final DDF output = assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
-        validateAssertionError(output, String.format("None of the audiences within Assertion '%s' matched the list of valid audiances",
-                response.getAssertions().get(0).getID()));
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("None of the audiences within Assertion '%s' matched the list of valid audiances",
+                        response.getAssertions().get(0).getID()));
     }
 
+    /**
+     * Test failure due to state recovery address.
+     * 
+     * @throws IOException
+     * @throws ResolverException 
+     */
+    @Test
+    public void testFailedStateAddress() throws IOException, ResolverException {
+        
+        final StateData data = buildStateData("foo");
+        data.setClientAddress("192.168.1.2");
+        final String stateToken = getStateToken(data);
+        
+        final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, "foo");
+        sign(response);
+        final DDF input = buildRemotedPOSTResponse(response, stateToken, response2.getCookies()[0]);
+
+        setApplicationRequest(APPLICATION_ID, input);
+        
+        validateError(EventIds.INVALID_MESSAGE,
+                String.format("SubjectConfirmationData/@InResponseTo for assertion '%s' did not match the valid value: null",
+                        response.getAssertions().get(0).getID()));
+    }
+    
     /**
      * Test successful flow.
      * 
@@ -616,7 +598,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     public void testSuccess() throws IOException {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -638,31 +620,11 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     @Test
     public void testSuccessWithState() throws IOException, ResolverException {
         
-        request2 = new MockHttpServletRequest();
-        response2 = new MockHttpServletResponse();
-        final StateData state = buildStateData("foo");
-        
-        final String stateToken;
-        
-        try (final ServiceableComponent<AgentResolver> resolver = agentResolver.getServiceableComponent()) {
-            final Agent agent = resolver.getComponent().resolveSingle(
-                    new CriteriaSet(new AgentCriterion(AGENT_ID)));
-            assert agent != null;
-            final Application app = agent.getApplication(APPLICATION_ID);
-            assert app != null;
-            stateToken = stateManager.preserveToStateToken(agent, app, state);
-        }
-        
-        final Cookie cookie = response2.getCookies()[0];
-        assert cookie != null;
+        final String stateToken = getStateToken(buildStateData("foo"));
         
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, "foo");
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, stateToken);        
-        input.getmember(RemotedHttpServletRequest.STRUCTURE_NAME)
-            .addmember("headers").structure()
-            .addmember("Cookie")
-            .unsafe_string(new String(cookie.getName() + '=' + cookie.getValue()).getBytes(StandardCharsets.UTF_8));
+        final DDF input = buildRemotedPOSTResponse(response, stateToken, response2.getCookies()[0]);
 
         setApplicationRequest(APPLICATION_ID, input);
         
@@ -693,7 +655,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
                         CollectionSupport.listOf("staff at example.org", "employee at example.org")));
         response.getAssertions().get(0).getAttributeStatements().add(statement);
         sign(response);
-        final DDF input = buildRemotedPOSTResponse(response, null);
+        final DDF input = buildRemotedPOSTResponse(response, null, null);
         setApplicationRequest(APPLICATION_ID, input);
 
         final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -778,6 +740,23 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         return output;
     }
     
+    /**
+     * Run the flow and verify an event is signalled, optionally
+     * ensuring an assertion validation message matches an expected message.
+     * 
+     * @param event event to check for
+     * @param assertionError optional message to scan for
+     */
+    private void validateError(@Nonnull final String event, @Nullable final String assertionError) {
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        final DDF output = assertOutputMessageEvent(result, event);
+        if (assertionError != null) {
+            validateAssertionError(output, assertionError);
+        }
+    }
+    
     /**
      * Tests the output contains token validation error starting with the designated string.
      * 
@@ -797,7 +776,6 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         Assert.assertTrue(msg != null && msg.startsWith(messagePrefix));
     }
     
-    
     /**
      * Builds a SAML response with some tailored data.
      * 
@@ -857,19 +835,21 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
      * 
      * @param response SAML response to encode
      * @param relayState relay state if any
+     * @param stateCookie the state cookie to attack to the input message if any
      * 
      * @return input object suitable for token consumer flow
      * 
      * @throws IOException on error 
      */
-    @Nonnull private DDF buildRemotedPOSTResponse(@Nonnull final Response response, @Nullable final String relayState)
+    @Nonnull private DDF buildRemotedPOSTResponse(@Nonnull final Response response, @Nullable final String relayState,
+            @Nullable Cookie stateCookie)
             throws IOException {
                 
         try (final ByteArrayOutputStream sink = new ByteArrayOutputStream()) {
             XMLObjectSupport.marshallToOutputStream(response, sink);
             final String base64 = Base64Support.encode(sink.toByteArray(), true);
             final DDF obj = new DDF(null).structure();
-            obj.addmember(ConsumerConstants.BASE_URL).unsafe_string(RESOURCE_URL.getBytes(StandardCharsets.UTF_8));
+            obj.addmember(ConsumerConstants.BASE_URL).unsafe_string(RESOURCE_URL.getBytes(StandardCharsets.UTF_8));            
             final DDF http = obj.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
             
             http.addmember(RemotedHttpServletRequest.METHOD).string("POST");
@@ -877,6 +857,11 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
             http.addmember(RemotedHttpServletRequest.CONTENT_TYPE).string("application/x-www-form-urlencoded");
             http.addmember(RemotedHttpServletRequest.REQUEST_URL).unsafe_string(RESPONSE_URL.getBytes(StandardCharsets.UTF_8));
             
+            if (stateCookie != null) {
+                http.addmember("headers").structure().addmember("Cookie")
+                    .unsafe_string(new String(stateCookie.getName() + '=' + stateCookie.getValue()).getBytes(StandardCharsets.UTF_8));
+            }
+            
             final List<Pair<String,String>> params;
             if (relayState != null) {
                 params = CollectionSupport.listOf(new Pair<>("SAMLResponse", base64),
@@ -931,5 +916,28 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         data.setRawResource(RESOURCE_URL.getBytes(StandardCharsets.UTF_8));
         return data;
     }
+
+    /**
+     * Generate a state token for the supplied data.
+     * 
+     * @param data state to preserve
+     * 
+     * @return the token to use as RelayState
+     * 
+     * @throws ResolverException
+     * @throws IOException
+     */
+    @Nonnull private String getStateToken(@Nonnull final StateData data) throws ResolverException, IOException {
+        try (final ServiceableComponent<AgentResolver> resolver = agentResolver.getServiceableComponent()) {
+            final Agent agent = resolver.getComponent().resolveSingle(
+                    new CriteriaSet(new AgentCriterion(AGENT_ID)));
+            assert agent != null;
+            final Application app = agent.getApplication(APPLICATION_ID);
+            assert app != null;
+            request2 = new MockHttpServletRequest();
+            response2 = new MockHttpServletResponse();
+            return stateManager.preserveToStateToken(agent, app, data);
+        }
+    }
     
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list