[java-plugin-shibd-saml] branch main updated: Stash RelayState when processing LogoutRequests.
Codeberg
noreply at shibboleth.net
Mon May 25 20:00:02 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/36b24f694a042037c38e5f14c6d2f71e1b5de1f3
The following commit(s) were added to refs/heads/main by this push:
new 36b24f6 Stash RelayState when processing LogoutRequests.
36b24f6 is described below
commit 36b24f694a042037c38e5f14c6d2f71e1b5de1f3
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon May 25 15:59:44 2026 -0400
Stash RelayState when processing LogoutRequests.
---
.../flows/saml2/SAML2LogoutConsumerFlowTest.java | 22 ++++++++++++++--------
.../saml2/profile/impl/ProcessLogoutRequest.java | 13 +++++++++----
.../profile/impl/ProcessLogoutRequestTest.java | 6 ++++++
3 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutConsumerFlowTest.java b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutConsumerFlowTest.java
index 0f9f1aa..c1a3510 100644
--- a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutConsumerFlowTest.java
+++ b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutConsumerFlowTest.java
@@ -27,6 +27,7 @@ import org.opensaml.core.xml.io.MarshallingException;
import org.opensaml.core.xml.util.XMLObjectSupport;
import org.opensaml.profile.context.ProfileRequestContext;
import org.opensaml.saml.common.SAMLObject;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.LogoutRequest;
import org.opensaml.saml.saml2.core.NameID;
@@ -62,6 +63,7 @@ import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.profile.IdPEventIds;
import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
import net.shibboleth.idp.test.PreferFileSystemApplicationContextInitializer;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.codec.Base64Support;
import net.shibboleth.shared.codec.EncodingException;
import net.shibboleth.shared.collection.CollectionSupport;
@@ -111,16 +113,19 @@ import net.shibboleth.sp.state.impl.PassthroughStateManager;
public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
/** Flow ID. */
- @Nonnull public static final String FLOW_ID = "sp/logout-consumer";
+ @Nonnull @NotEmpty public static final String FLOW_ID = "sp/logout-consumer";
/** Issuer. */
- @Nonnull public static final String ISSUER = "https://idp.example.org";
+ @Nonnull @NotEmpty public static final String ISSUER = "https://idp.example.org";
/** Audience. */
- @Nonnull public static final String AUDIENCE = "https://testsp.example.org";
+ @Nonnull @NotEmpty public static final String AUDIENCE = "https://testsp.example.org";
/** ACS URL. */
- @Nonnull public static final String RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/SAML2/SLO/POST";
+ @Nonnull @NotEmpty public static final String RESPONSE_URL = "https://sp.example.org/Shibboleth.sso/SAML2/SLO/POST";
+
+ /** Relay state. */
+ @Nonnull @NotEmpty public static final String RELAY_STATE = "dummy";
@Autowired
@Qualifier("shibboleth.DataSealer")
@@ -239,7 +244,7 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
*/
@Test
public void testRequestUnverified() throws IOException {
- final DDF input = buildRemotedPOSTMessage(buildLogoutRequest(ISSUER + "/bad"), null, null);
+ final DDF input = buildRemotedPOSTMessage(buildLogoutRequest(ISSUER + "/bad"), RELAY_STATE, null);
setApplicationRequest(APPLICATION_ID, input);
validateError(IdPEventIds.INVALID_PROFILE_CONFIG);
@@ -254,7 +259,7 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
public void testRequestNoSession() throws Exception {
final LogoutRequest request = buildLogoutRequest(ISSUER);
sign(request);
- final DDF input = buildRemotedPOSTMessage(request, null, null);
+ final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
setApplicationRequest(APPLICATION_ID, input);
validateLogoutRequestResult(false);
@@ -269,7 +274,7 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
public void testRequestNoMatch() throws Exception {
final LogoutRequest request = buildLogoutRequest(ISSUER);
sign(request);
- final DDF input = buildRemotedPOSTMessage(request, null, null);
+ final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
"<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion'"
+ "' SPProvidedID='" + ISSUER + "'>jdoe at example.org</NameID>");
@@ -287,7 +292,7 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
public void testRequestSuccess() throws Exception {
final LogoutRequest request = buildLogoutRequest(ISSUER);
sign(request);
- final DDF input = buildRemotedPOSTMessage(request, null, null);
+ final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
"<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='"
+ NameIDType.EMAIL + "' SPProvidedID='" + ISSUER + "'>jdoe at example.org</NameID>");
@@ -344,6 +349,7 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
assert issuer != null;
Assert.assertEquals(stateData.getAuthenticationAuthority(), issuer.getValue());
Assert.assertEquals(stateData.getRequestID(), request.getID());
+ Assert.assertEquals(stateData.getResource(), SAMLBindingSupport.getRelayState(prc.ensureInboundMessageContext()));
return output;
}
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequest.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequest.java
index ead2a3b..58fef83 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequest.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequest.java
@@ -30,6 +30,7 @@ import org.opensaml.core.xml.util.XMLObjectSupport;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.LogoutRequest;
import org.opensaml.saml.saml2.core.NameID;
@@ -225,7 +226,7 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
final NameID requestedNameID = logoutRequest.getNameID();
if (requestedNameID == null) {
log.info("{} No NameID in logout request", getLogPrefix());
- addToken(issuer, false);
+ addToken(profileRequestContext, issuer, false);
return;
}
@@ -235,7 +236,7 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
: null;
if (pickled == null) {
log.info("{} No encoded NameID found in input message", getLogPrefix());
- addToken(issuer, false);
+ addToken(profileRequestContext, issuer, false);
return;
}
@@ -254,7 +255,7 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
final boolean matched = requestMatchesSession(profileRequestContext, issuer, sessionNameID);
log.debug("{} LogoutRequest {} session from Agent", getLogPrefix(), matched ? "matched" : "did not match");
- addToken(issuer, matched);
+ addToken(profileRequestContext, issuer, matched);
}
/**
@@ -336,10 +337,12 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
*
* <p>The token tracks the request ID and the issuer.</p>
*
+ * @param profileRequestContext profile request context
* @param issuer issuer of request
* @param matched matched signal
*/
- private void addToken(@Nullable final Issuer issuer, final boolean matched) {
+ private void addToken(@Nonnull final ProfileRequestContext profileRequestContext, @Nullable final Issuer issuer,
+ final boolean matched) {
output.addmember(MATCHED_PARAM).integer(matched ? 1 : 0);
@@ -347,6 +350,8 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
state.setRequestID(logoutRequest.getID());
state.setAuthenticationAuthority(issuer != null ? issuer.getValue() : null);
+ // We have no need for this field's usual purpose so this is a simple way to store off RelayState.
+ state.setResource(SAMLBindingSupport.getRelayState(profileRequestContext.ensureInboundMessageContext()));
try {
final String token = stateManager.preserveToStateToken(ensureAgent(), ensureApplication(), state);
diff --git a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequestTest.java b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequestTest.java
index e559e66..be836dc 100644
--- a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequestTest.java
+++ b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutRequestTest.java
@@ -17,11 +17,13 @@ package net.shibboleth.sp.saml.saml2.profile.impl;
import java.io.IOException;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.profile.action.EventIds;
import org.opensaml.saml.common.SAMLObjectBuilder;
+import org.opensaml.saml.common.binding.SAMLBindingSupport;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.LogoutRequest;
import org.opensaml.saml.saml2.core.LogoutResponse;
@@ -59,6 +61,8 @@ import net.shibboleth.sp.testing.TestResourceConverter;
@SuppressWarnings("javadoc")
public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
+ @Nonnull private static final String RELAY_STATE = "dummy";
+
private Resource keystoreResource;
private Resource versionResource;
private DataSealer sealer;
@@ -311,6 +315,7 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
final LogoutRequest request = SAML2ActionTestingSupport.buildLogoutRequest(
SAML2ActionTestingSupport.buildNameID("jdoe"));
prc.ensureInboundMessageContext().setMessage(request);
+ SAMLBindingSupport.setRelayState(prc.ensureInboundMessageContext(), RELAY_STATE);
}
/**
@@ -338,5 +343,6 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
assert issuer != null;
Assert.assertEquals(data.getAuthenticationAuthority(), issuer.getValue());
Assert.assertEquals(data.getRequestID(), request.getID());
+ Assert.assertEquals(data.getResource(), RELAY_STATE);
}
}
\ 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