[java-plugin-shibd-saml] branch main updated: Add SOAP header checks for ECP tests.

Codeberg noreply at shibboleth.net
Mon Aug 10 15:23:59 UTC 2026


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

codeberg pushed a commit to branch main
in repository java-plugin-shibd-saml.

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

The following commit(s) were added to refs/heads/main by this push:
     new be4444b  Add SOAP header checks for ECP tests.
be4444b is described below

commit be4444b8fab79300d8f66f3d4cceb419f37dd7be
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Aug 10 11:23:45 2026 -0400

    Add SOAP header checks for ECP tests.
---
 .../flows/saml2/ECPSessionInitiatorFlowTest.java   | 76 ++++++++++++++++++++--
 .../binding/impl/AddECPRequestHeaderHandler.java   |  6 +-
 2 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/ECPSessionInitiatorFlowTest.java b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/ECPSessionInitiatorFlowTest.java
index 4b7074f..b3be667 100644
--- a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/ECPSessionInitiatorFlowTest.java
+++ b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/ECPSessionInitiatorFlowTest.java
@@ -22,6 +22,7 @@ import java.time.Instant;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.UnmarshallingException;
 import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.profile.action.EventIds;
@@ -31,7 +32,12 @@ import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.core.AuthnRequest;
 import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.NameIDPolicy;
+import org.opensaml.saml.saml2.ecp.RelayState;
+import org.opensaml.saml.saml2.ecp.Request;
+import org.opensaml.soap.soap11.ActorBearing;
+import org.opensaml.soap.soap11.Body;
 import org.opensaml.soap.soap11.Envelope;
+import org.opensaml.soap.soap11.Header;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.web.WebAppConfiguration;
 import org.springframework.webflow.executor.FlowExecutionResult;
@@ -41,7 +47,7 @@ import org.testng.annotations.Test;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
 import net.shibboleth.idp.test.PreferFileSystemApplicationContextInitializer;
-import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.ConstraintViolationException;
 import net.shibboleth.shared.xml.XMLParserException;
 import net.shibboleth.sp.context.AgentRequestContext;
 import net.shibboleth.sp.ddf.DDF;
@@ -53,7 +59,7 @@ import net.shibboleth.sp.profile.SPConstants;
 import net.shibboleth.sp.saml.saml2.profile.SAML2InitiatorConstants;
 
 /**
- * Unit test for the SP session-initiator flow.
+ * Unit test for the ECP session-initiator flow.
  */
 @ContextConfiguration(
         locations = {
@@ -270,7 +276,7 @@ public class ECPSessionInitiatorFlowTest extends AbstractSPFlowTest {
         final byte[] body = http.getmember(RemotedHttpServletResponse.RESPONSE).getmember(RemotedHttpServletResponse.DATA).unsafe_string();
         assert body != null;
         final Envelope env = decodeSOAPEnvelope(body);
-        final AuthnRequest authnRequest = (AuthnRequest) Constraint.isNotNull(env.getBody(), "Body was null").getUnknownXMLObjects().get(0);
+        final AuthnRequest authnRequest = validateSOAPEnvelope(env, SAMLBindingSupport.getRelayState(prc.ensureOutboundMessageContext()));
         
         Assert.assertNotNull(authnRequest.getID());
         Assert.assertEquals(authnRequest.getProtocolBinding(), SAMLConstants.SAML2_PAOS_BINDING_URI);
@@ -316,7 +322,7 @@ public class ECPSessionInitiatorFlowTest extends AbstractSPFlowTest {
      * @throws IOException 
      * @throws UnmarshallingException 
      */
-    @Nonnull protected Envelope decodeSOAPEnvelope(@Nonnull final byte[] body)
+    @Nonnull private Envelope decodeSOAPEnvelope(@Nonnull final byte[] body)
             throws IOException, UnmarshallingException, XMLParserException {
         
         
@@ -324,5 +330,67 @@ public class ECPSessionInitiatorFlowTest extends AbstractSPFlowTest {
             return (Envelope) XMLObjectSupport.unmarshallFromInputStream(parserPool, in);
         }
     }
+    
+    /**
+     * Validate SOAP content.
+     * 
+     * @param env envelope
+     * @param relayState relay state from binding if any
+     * 
+     * @return the body payload
+     */
+    @Nonnull private AuthnRequest validateSOAPEnvelope(@Nonnull final Envelope env, @Nullable final String relayState) {
+
+        final AuthnRequest request;
+        final Body body = env.getBody();
+        assert body != null;
+        if (body.getUnknownXMLObjects().get(0) instanceof AuthnRequest req) {
+            request = req;
+        } else {
+            throw new ConstraintViolationException("Body did not contain AuthnRequest");
+        }
+        
+        final Header header = env.getHeader();
+        assert header != null;
+        
+        Assert.assertEquals(header.getUnknownXMLObjects().size(), 3);
+        
+        for (final XMLObject block : header.getUnknownXMLObjects()) {
+            if (block instanceof net.shibboleth.sp.liberty.paos.Request paos) {
+                
+                Assert.assertEquals(paos.isSOAP11MustUnderstand(), true);
+                Assert.assertEquals(paos.getSOAP11Actor(), ActorBearing.SOAP11_ACTOR_NEXT);
+                Assert.assertEquals(paos.getMessageID(), request.getID());
+                Assert.assertEquals(paos.getResponseConsumerURL(), request.getAssertionConsumerServiceURL());
+                Assert.assertEquals(paos.getService(), SAMLConstants.SAML20ECP_NS);
+                
+            } else if (block instanceof Request ecp) {
+                
+                final Issuer reqIssuer = request.getIssuer();
+                final Issuer ecpIssuer = ecp.getIssuer();
+                assert reqIssuer != null && ecpIssuer != null;
+                Assert.assertEquals(reqIssuer.getValue(), ecpIssuer.getValue());
+                
+                final Boolean reqPassive = request.isPassive();
+                final Boolean ecpPassive = ecp.isPassive();
+                Assert.assertEquals(ecpPassive, reqPassive != null && reqPassive);
+                
+                Assert.assertNull(ecp.getProviderName());
+                Assert.assertNull(ecp.getIDPList());
+                Assert.assertEquals(ecp.isSOAP11MustUnderstand(), true);
+                Assert.assertEquals(ecp.getSOAP11Actor(), ActorBearing.SOAP11_ACTOR_NEXT);
+                
+            } else if (block instanceof RelayState state) {
+                
+                Assert.assertEquals(state.getValue(), relayState);
+                Assert.assertEquals(state.isSOAP11MustUnderstand(), true);
+                Assert.assertEquals(state.getSOAP11Actor(), ActorBearing.SOAP11_ACTOR_NEXT);
+                
+            }
+        }
+        
+        return req;
+        
+    }
 
 }
\ No newline at end of file
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/binding/impl/AddECPRequestHeaderHandler.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/binding/impl/AddECPRequestHeaderHandler.java
index b2e2644..7fb890f 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/binding/impl/AddECPRequestHeaderHandler.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/binding/impl/AddECPRequestHeaderHandler.java
@@ -82,10 +82,10 @@ public class AddECPRequestHeaderHandler extends AbstractMessageHandler {
         final Request header = requestBuilder.buildObject(Request.DEFAULT_ELEMENT_NAME);
         
         // IsPassive in this header block defaults to true if absent (no idea why we did that).
+        // OpenSAML also has the wrong default on this, so at least for test sanity, I'm setting
+        // it either way to the expected value.
         final Boolean passive = authnRequest.isPassive();
-        if (passive == null || !passive) {
-            header.setPassive(false);
-        }
+        header.setPassive(passive != null && passive);
         
         final Issuer issuer = authnRequest.getIssuer();
         if (issuer != null) {

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


More information about the commits mailing list