[java-plugin-shibd-saml] branch main updated: Tests/fixes for legacy response URL handling.

Scott Cantor cantor.2 at osu.edu
Mon Feb 10 15:38:20 UTC 2025


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=2c2582e236400bfd504bd80b4e6880d1fbfe3c72

The following commit(s) were added to refs/heads/main by this push:
     new 2c2582e  Tests/fixes for legacy response URL handling.
2c2582e is described below

commit 2c2582e236400bfd504bd80b4e6880d1fbfe3c72
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Feb 10 10:38:17 2025 -0500

    Tests/fixes for legacy response URL handling.
---
 .../idp/flows/sp/initiator/saml2/saml2-beans.xml   |   9 +-
 .../flows/saml2/SAML2SessionInitiatorFlowTest.java | 102 ++++++++++++++++++++-
 .../idp/module/conf/sp/saml-test-agents.xml        |  11 +++
 .../saml/saml2/profile/impl/AddAuthnRequest.java   |   5 +-
 4 files changed, 116 insertions(+), 11 deletions(-)

diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/saml2/saml2-beans.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/saml2/saml2-beans.xml
index 3f69126..6c72d4f 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/saml2/saml2-beans.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/initiator/saml2/saml2-beans.xml
@@ -67,20 +67,21 @@
 
     <util:map id="InboundSAML2BindingMap">
         <entry key="POST">
-            <ref bean="shibboleth.Binding.SAML2POST" />
+            <util:constant static-field="org.opensaml.saml.common.xml.SAMLConstants.SAML2_POST_BINDING_URI" />
         </entry>
         <entry key="POST-SimpleSign">
-            <ref bean="shibboleth.Binding.SAML2POSTSimpleSign" />
+            <util:constant static-field="org.opensaml.saml.common.xml.SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI" />
         </entry>
         <entry key="Artifact">
-            <ref bean="shibboleth.Binding.SAML2Artifact" />
+            <util:constant static-field="org.opensaml.saml.common.xml.SAMLConstants.SAML2_ARTIFACT_BINDING_URI" />
         </entry>
     </util:map>
 
     <bean id="AddAuthnRequest"
             class="net.shibboleth.sp.saml.saml2.profile.impl.AddAuthnRequest" scope="prototype"
             p:overwriteExisting="true"
-            p:nameIDLookupStrategy="#{getObject('%{sp.authn.SAML.NameIDLookupStrategy:}'.trim())}">
+            p:nameIDLookupStrategy="#{getObject('%{sp.authn.SAML.NameIDLookupStrategy:}'.trim())}"
+            p:inboundBindingMap-ref="InboundSAML2BindingMap">
         <property name="identifierGeneratorLookupStrategy">
             <bean class="net.shibboleth.profile.config.navigate.IdentifierGenerationStrategyLookupFunction"
                 p:defaultIdentifierGenerationStrategy-ref="shibboleth.DefaultIdentifierGenerationStrategy" />
diff --git a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2SessionInitiatorFlowTest.java b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2SessionInitiatorFlowTest.java
index 25c9bc5..cc4ec2c 100644
--- a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2SessionInitiatorFlowTest.java
+++ b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2SessionInitiatorFlowTest.java
@@ -27,6 +27,7 @@ import org.opensaml.messaging.decoder.MessageDecodingException;
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.saml.common.SAMLObject;
 import org.opensaml.saml.common.binding.SAMLBindingSupport;
+import org.opensaml.saml.common.xml.SAMLConstants;
 import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
 import org.opensaml.saml.saml2.core.AuthnContext;
 import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration;
@@ -70,7 +71,13 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
     @Nonnull public static final String FLOW_ID = "sp/session-initiator";
 
     /** ACS URL. */
-    @Nonnull public static final String RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/SAML2/POST";
+    @Nonnull public static final String RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/ACS";
+
+    /** POST ACS URL. */
+    @Nonnull public static final String POST_RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/SAML2/POST";
+
+    /** Artifact ACS URL. */
+    @Nonnull public static final String ARTIFACT_RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/SAML2/Artifact";
 
     /** Constructor. */
     protected SAML2SessionInitiatorFlowTest() {
@@ -170,15 +177,102 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
         assertFlowExecutionResult(result, FLOW_ID);
         assertFlowExecutionOutcome(result.getOutcome());
         
+        assertOutputMessageSuccess(result);
+        final AuthnRequest req = validateOutputMessage(result, null);
+        Assert.assertEquals(req.getAssertionConsumerServiceURL(), RESPONSE_URL);
+        Assert.assertEquals(req.getProtocolBinding(), SAMLConstants.SAML2_POST_BINDING_URI);
+        Assert.assertNull(req.getSubject());
+        Assert.assertNull(req.getRequestedAuthnContext());
+        Assert.assertNull(req.getScoping());
+        assertFalse(req.isForceAuthn());
+        assertFalse(req.isPassive());
+    }
+    
+    /**
+     * Test legacy response URL success case picking first URL.
+     * 
+     * @throws IOException 
+     * @throws MessageDecodingException 
+     */
+    @Test
+    public void testFirstResponseURL() throws IOException, MessageDecodingException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF(null).structure();
+        final DDF endpoints = input.addmember(InitiatorConstants.RESPONSE_URL).list();
+        endpoints.add(new DDF("POST").string(POST_RESPONSE_URL));
+        endpoints.add(new DDF("Artifact").string(ARTIFACT_RESPONSE_URL));
+        setApplicationRequest(APPLICATION_ID, input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
+        assertOutputMessageSuccess(result);
+        final AuthnRequest req = validateOutputMessage(result, null);
+        Assert.assertNull(req.getSubject());
+        Assert.assertNull(req.getRequestedAuthnContext());
+        Assert.assertNull(req.getScoping());
+        Assert.assertEquals(req.getAssertionConsumerServiceURL(), POST_RESPONSE_URL);
+        Assert.assertEquals(req.getProtocolBinding(), SAMLConstants.SAML2_POST_BINDING_URI);
+        assertFalse(req.isForceAuthn());
+        assertFalse(req.isPassive());
+    }
+
+    /**
+     * Test legacy response URL success case picking artifact URL.
+     * 
+     * @throws IOException 
+     * @throws MessageDecodingException 
+     */
+    @Test
+    public void testArtifactResponseURL() throws IOException, MessageDecodingException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF(null).structure();
+        final DDF endpoints = input.addmember(InitiatorConstants.RESPONSE_URL).list();
+        endpoints.add(new DDF("POST").string(POST_RESPONSE_URL));
+        endpoints.add(new DDF("Artifact").string(ARTIFACT_RESPONSE_URL));
+        setApplicationRequest("response-binding", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        
         assertOutputMessageSuccess(result);
         final AuthnRequest req = validateOutputMessage(result, null);
         Assert.assertNull(req.getSubject());
         Assert.assertNull(req.getRequestedAuthnContext());
         Assert.assertNull(req.getScoping());
+        Assert.assertEquals(req.getAssertionConsumerServiceURL(), ARTIFACT_RESPONSE_URL);
+        Assert.assertEquals(req.getProtocolBinding(), SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
         assertFalse(req.isForceAuthn());
         assertFalse(req.isPassive());
     }
 
+    /**
+     * Test legacy response URL failure when binding doesn't match.
+     * 
+     * @throws IOException 
+     * @throws MessageDecodingException 
+     */
+    @Test
+    public void testNoMatchingResponseURL() throws IOException, MessageDecodingException {
+        setDefaultAuth();
+        
+        final DDF input = new DDF(null).structure();
+        final DDF endpoints = input.addmember(InitiatorConstants.RESPONSE_URL).list();
+        endpoints.add(new DDF("POST").string(POST_RESPONSE_URL));
+        endpoints.add(new DDF("NoMatch").string(ARTIFACT_RESPONSE_URL));
+        setApplicationRequest("response-binding", input);
+
+        final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+        assertFlowExecutionResult(result, FLOW_ID);
+        assertFlowExecutionOutcome(result.getOutcome());
+        assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
+    }
+
+
     /**
      * Test simple success case with computed relay state.
      * 
@@ -201,6 +295,8 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
         
         assertOutputMessageSuccess(result);
         final AuthnRequest req = validateOutputMessage(result, null);
+        Assert.assertEquals(req.getAssertionConsumerServiceURL(), RESPONSE_URL);
+        Assert.assertEquals(req.getProtocolBinding(), SAMLConstants.SAML2_POST_BINDING_URI);
         Assert.assertNull(req.getSubject());
         Assert.assertNull(req.getRequestedAuthnContext());
         Assert.assertNull(req.getScoping());
@@ -461,9 +557,7 @@ public class SAML2SessionInitiatorFlowTest extends AbstractSPFlowTest {
         assert authnRequest != null;
         Assert.assertNotNull(authnRequest.getID());
         Assert.assertTrue(Instant.now().isAfter(authnRequest.getIssueInstant()));
-        
-        Assert.assertEquals(authnRequest.getAssertionConsumerServiceURL(), RESPONSE_URL);
-        
+                
         final NameIDPolicy pol = authnRequest.getNameIDPolicy();
         assert pol != null;
         assertTrue(pol.getAllowCreate());
diff --git a/sp-saml-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/saml-test-agents.xml b/sp-saml-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/saml-test-agents.xml
index bac6623..3b60dbe 100644
--- a/sp-saml-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/saml-test-agents.xml
+++ b/sp-saml-conf-impl/src/test/resources/net/shibboleth/idp/module/conf/sp/saml-test-agents.xml
@@ -25,6 +25,11 @@
                     p:authenticatingAuthority="https://idp.example.org"
                     p:profileConfigurations-ref="test.featureBlockingProfileConfigurations" />
 
+                <bean p:id="response-binding" parent="shibboleth.Application"
+                    p:issuer="https://testsp.example.org"
+                    p:authenticatingAuthority="https://idp.example.org"
+                    p:profileConfigurations-ref="test.responseBindingProfileConfigurations" />
+
                 <bean p:id="no-metadata" parent="shibboleth.Application"
                     p:issuer="https://testsp.example.org"
                     p:authenticatingAuthority="https://unknown.example.org"
@@ -54,6 +59,12 @@
         <ref bean="SAML2.Logout" />
     </util:list>
 
+    <util:list id="test.responseBindingProfileConfigurations">
+        <bean parent="SAML2.SSO" p:responseBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" />
+        <ref bean="SAML2.ECP" />
+        <ref bean="SAML2.Logout" />
+    </util:list>
+
     <util:list id="test.featureBlockingProfileConfigurations">
         <bean parent="SAML2.SSO" p:disallowedFeatures="0x1F" />
         <ref bean="SAML2.ECP" />
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
index 1d57a4c..c659cfa 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/AddAuthnRequest.java
@@ -385,12 +385,11 @@ public class AddAuthnRequest extends AbstractApplicationAction {
         }
         
         final String binding = profileConfiguration.getResponseBinding(profileRequestContext);
-        if (binding == null || inboundBindingMap.isEmpty()) {
+        if (binding == null) {
             // We have no means of determining which of multiple endpoints would match the intended binding,
             // or no specific binding is required, so we have to just pick the first endpoint.
             authnRequest.setAssertionConsumerServiceURL(endpoints.get(0).string());
-            // Protocol binding comes from config, may be null.
-            authnRequest.setProtocolBinding(binding);
+            authnRequest.setProtocolBinding(null);
             return true;
         }
 

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


More information about the commits mailing list