[java-plugin-shibd-saml] branch dev/StateMgmtWIP updated: Incorporate new state mgmt into consumer flow.
Codeberg
noreply at shibboleth.net
Tue Apr 28 17:54:37 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/595995b3b0f0098f02af7ed936f7a90b1afca35c
The following commit(s) were added to refs/heads/dev/StateMgmtWIP by this push:
new 595995b Incorporate new state mgmt into consumer flow.
595995b is described below
commit 595995b3b0f0098f02af7ed936f7a90b1afca35c
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Apr 28 13:54:26 2026 -0400
Incorporate new state mgmt into consumer flow.
---
.../context/navigate/RequestIDLookupFunction.java | 43 ++++++++++++++++++
.../saml/saml2/context/navigate/package-info.java | 18 ++++++++
.../idp/flows/sp/consumer/saml2/saml2-beans.xml | 28 +++---------
.../idp/flows/sp/consumer/saml2/saml2-flow.xml | 3 +-
.../flows/saml2/SAML2TokenConsumerFlowTest.java | 51 ++++++++++++----------
5 files changed, 97 insertions(+), 46 deletions(-)
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/RequestIDLookupFunction.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/RequestIDLookupFunction.java
new file mode 100644
index 0000000..941aded
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/RequestIDLookupFunction.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.sp.saml.saml2.context.navigate;
+
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.navigate.ContextDataLookupFunction;
+
+import net.shibboleth.sp.context.StateDataContext;
+import net.shibboleth.sp.saml.saml2.SAMLStateData;
+import net.shibboleth.sp.state.StateData;
+
+/**
+ * Lookup strategy for accessing request ID via {@link StateDataContext#getStateData()} and
+ * {@link SAMLStateData#getRequestID()}.
+ */
+public class RequestIDLookupFunction implements ContextDataLookupFunction<StateDataContext,String> {
+
+ /** {@inheritDoc} */
+ @Nullable public String apply(@Nullable final StateDataContext input) {
+ if (input != null) {
+ final StateData data = input.getStateData();
+ if (data instanceof SAMLStateData saml) {
+ return saml.getRequestID();
+ }
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/package-info.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/package-info.java
new file mode 100644
index 0000000..f3eccb3
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/context/navigate/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Functions for navigating SAML-specific context information.
+ */
+package net.shibboleth.sp.saml.saml2.context.navigate;
\ No newline at end of file
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 b502bab..99f3e30 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
@@ -12,10 +12,10 @@
<import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/saml2-common-beans.xml" />
- <bean id="MapStateTokenToResource"
- class="net.shibboleth.sp.profile.impl.MapStateTokenToResource" scope="prototype"
- p:createOutputObjects="true"
- p:stateTokenLookupStrategy-ref="RelayStateLookup" />
+ <bean id="RecoverStateData"
+ class="net.shibboleth.sp.profile.impl.RecoverStateData" scope="prototype"
+ p:stateTokenLookupStrategy-ref="RelayStateLookup"
+ p:stateDataClass="net.shibboleth.sp.saml.saml2.SAMLStateData" />
<bean id="RelayStateLookup" parent="shibboleth.Functions.Compose">
<constructor-arg name="g">
@@ -51,12 +51,6 @@
</constructor-arg>
</bean>
- <bean id="ProcessCorrelationCookie" class="net.shibboleth.sp.profile.impl.ProcessCorrelationCookie" scope="prototype"
- p:cookieManager-ref="shibboleth.sp.RemotedCookieManager"
- p:cookiePrefix="%{sp.correlation.cookiePrefix:__Host-shibsp_req_}"
- p:createOutputObjects="true"
- p:stateTokenLookupStrategy-ref="RelayStateLookup" />
-
<bean id="HandleResponse" class="net.shibboleth.sp.profile.impl.WebFlowMessageHandlerAdaptor" scope="prototype"
c:executionDirection="INBOUND">
<constructor-arg>
@@ -149,19 +143,11 @@
<property name="inResponseTo">
<bean parent="shibboleth.Functions.Compose">
<constructor-arg name="g">
- <bean class="net.shibboleth.sp.profile.context.navigate.MessageCorrelationIDLookupFunction" />
+ <bean class="net.shibboleth.sp.saml.saml2.context.navigate.RequestIDLookupFunction" />
</constructor-arg>
<constructor-arg name="f">
- <bean parent="shibboleth.Functions.Compose">
- <constructor-arg name="g">
- <bean class="org.opensaml.messaging.context.navigate.ChildContextLookup"
- c:type="#{ T(net.shibboleth.sp.context.TokenConsumerContext) }" />
- </constructor-arg>
- <constructor-arg name="f">
- <bean class="org.opensaml.messaging.context.navigate.ChildContextLookup"
- c:type="#{ T(net.shibboleth.sp.context.AgentRequestContext) }" />
- </constructor-arg>
- </bean>
+ <bean class="org.opensaml.messaging.context.navigate.ChildContextLookup"
+ c:type="#{ T(net.shibboleth.sp.context.StateDataContext) }" />
</constructor-arg>
</bean>
</property>
diff --git a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-flow.xml b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-flow.xml
index c4f89e8..b298db8 100644
--- a/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-flow.xml
+++ b/sp-saml-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/consumer/saml2/saml2-flow.xml
@@ -8,11 +8,10 @@
<evaluate expression="DecodeMessage" />
<!-- <evaluate expression="PostDecodePopulateAuditContext" />-->
- <evaluate expression="MapStateTokenToResource" />
+ <evaluate expression="RecoverStateData" />
<evaluate expression="CheckMessageVersion" />
<evaluate expression="HandleNoPassive" />
- <evaluate expression="ProcessCorrelationCookie" />
<evaluate expression="SAMLProtocolAndRole" />
<evaluate expression="SAMLMetadataLookup" />
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 a589534..b047e9e 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
@@ -156,7 +156,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testErrorStatus() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.RESPONDER);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.RESPONDER, null);
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
setApplicationRequest(APPLICATION_ID, input);
@@ -174,7 +174,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testUnverified() throws IOException {
- final DDF input = buildRemotedPOSTResponse(buildSAMLResponse(ISSUER + "/bad", StatusCode.SUCCESS));
+ final DDF input = buildRemotedPOSTResponse(buildSAMLResponse(ISSUER + "/bad", StatusCode.SUCCESS, null));
setApplicationRequest(APPLICATION_ID, input);
final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
@@ -190,7 +190,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testExpired() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
response.setIssueInstant(Instant.EPOCH);
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
@@ -209,7 +209,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testBadDestination() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
response.setDestination(RESPONSE_URL + "/bad");
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
@@ -228,7 +228,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testAssertionExpired() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
response.getAssertions().get(0).setIssueInstant(Instant.now().minusSeconds(1800));
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
@@ -248,7 +248,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testSubjectLocality() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final SubjectLocality locality = response.getAssertions().get(0).getAuthnStatements().get(0).getSubjectLocality();
assert locality != null;
locality.setAddress("127.0.0.1");
@@ -271,7 +271,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testBadConfirmationAddress() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Subject subject = response.getAssertions().get(0).getSubject();
assert subject != null;
final SubjectConfirmationData data = subject.getSubjectConfirmations().get(0).getSubjectConfirmationData();
@@ -296,7 +296,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testBadConfirmationMethod() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Subject subject = response.getAssertions().get(0).getSubject();
assert subject != null;
subject.getSubjectConfirmations().get(0).setMethod(SubjectConfirmation.METHOD_SENDER_VOUCHES);
@@ -319,7 +319,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testNoNotOnOrAfter() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Subject subject = response.getAssertions().get(0).getSubject();
assert subject != null;
final SubjectConfirmationData data = subject.getSubjectConfirmations().get(0).getSubjectConfirmationData();
@@ -344,7 +344,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testNoRecipient() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Subject subject = response.getAssertions().get(0).getSubject();
assert subject != null;
final SubjectConfirmationData data = subject.getSubjectConfirmations().get(0).getSubjectConfirmationData();
@@ -369,7 +369,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testBadRecipient() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Subject subject = response.getAssertions().get(0).getSubject();
assert subject != null;
final SubjectConfirmationData data = subject.getSubjectConfirmations().get(0).getSubjectConfirmationData();
@@ -394,7 +394,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testAssertionBadIssuer() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
response.getAssertions().get(0).setIssuer(SAML2ActionTestingSupport.buildIssuer(ISSUER + "bad"));
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
@@ -416,7 +416,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testAssertionBadIssuerFormat() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Issuer issuer = SAML2ActionTestingSupport.buildIssuer(ISSUER);
issuer.setFormat(NameIDType.EMAIL);
response.getAssertions().get(0).setIssuer(issuer);
@@ -438,7 +438,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testUnsigned() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final DDF input = buildRemotedPOSTResponse(response);
setApplicationRequest(APPLICATION_ID, input);
@@ -456,7 +456,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testNoConditions() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
response.getAssertions().get(0).setConditions(null);
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
@@ -476,7 +476,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testExpiredCondition() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Conditions conditions = response.getAssertions().get(0).getConditions();
assert conditions != null;
conditions.setNotOnOrAfter(Instant.now().minusSeconds(300));
@@ -499,7 +499,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testBadAudience() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final Conditions conditions = response.getAssertions().get(0).getConditions();
assert conditions != null;
conditions.getAudienceRestrictions().get(0).getAudiences().get(0).setURI(AUDIENCE + "/bad");
@@ -522,7 +522,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testSuccess() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
sign(response);
final DDF input = buildRemotedPOSTResponse(response);
setApplicationRequest(APPLICATION_ID, input);
@@ -544,7 +544,7 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testSuccessAttributes() throws IOException {
- final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS);
+ final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
final AttributeStatement statement = SAML2ActionTestingSupport.buildAttributeStatement();
statement.getAttributes().add(
SAML2ActionTestingSupport.buildAttribute("urn:oid:2.16.840.1.113730.3.1.241", Attribute.URI_REFERENCE,
@@ -664,13 +664,15 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
*
* @param issuer issuer value
* @param code status code string
+ * @param requestID ID to place in InResponseTp
*
* @return input object suitable for token consumer flow
*/
- @Nonnull private Response buildSAMLResponse(@Nonnull final String issuer, @Nonnull final String code) {
+ @Nonnull private Response buildSAMLResponse(@Nonnull final String issuer, @Nonnull final String code, @Nullable final String requestID) {
final Response response = SAML2ActionTestingSupport.buildResponse();
response.setID(idGenerator.generateIdentifier());
+ response.setInResponseTo(requestID);
response.setIssueInstant(Instant.now());
response.setDestination(RESPONSE_URL);
response.setIssuer(SAML2ActionTestingSupport.buildIssuer(issuer));
@@ -687,9 +689,12 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
assert nameID != null;
nameID.setFormat(NameIDType.EMAIL);
- subject.getSubjectConfirmations().add(
- SAML2ActionTestingSupport.buildSubjectConfirmation(
- SubjectConfirmation.METHOD_BEARER, RESPONSE_URL, "192.168.1.1"));
+ final SubjectConfirmation sc = SAML2ActionTestingSupport.buildSubjectConfirmation(
+ SubjectConfirmation.METHOD_BEARER, RESPONSE_URL, "192.168.1.1");
+ final SubjectConfirmationData scdata = sc.getSubjectConfirmationData();
+ assert scdata != null;
+ scdata.setInResponseTo(requestID);
+ subject.getSubjectConfirmations().add(sc);
assertion.setSubject(subject);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list