[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