[java-plugin-shibd-saml] branch main updated: Move opaque session data handling to support class.

Codeberg noreply at shibboleth.net
Mon Jun 1 19:51:58 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/82bb68dde4bf8a153cd5515f8da5564c598bbfdb

The following commit(s) were added to refs/heads/main by this push:
     new 82bb68d  Move opaque session data handling to support class.
82bb68d is described below

commit 82bb68dde4bf8a153cd5515f8da5564c598bbfdb
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Jun 1 15:51:17 2026 -0400

    Move opaque session data handling to support class.
---
 .../sp/saml/saml2/SessionDataSupport.java          | 97 ++++++++++++++++++++++
 .../flows/saml2/SAML2LogoutConsumerFlowTest.java   | 21 +++--
 .../flows/saml2/SAML2LogoutInitiatorFlowTest.java  | 71 ++++++++++------
 .../flows/saml2/SAML2TokenConsumerFlowTest.java    | 54 +++++-------
 .../saml2/profile/impl/PrepareAgentResponse.java   | 21 +----
 .../impl/ProcessLogoutInitiatorRequest.java        | 31 +++----
 .../saml2/profile/impl/ProcessLogoutRequest.java   | 11 +--
 .../profile/impl/PrepareAgentResponseTest.java     | 44 +++-------
 .../impl/ProcessLogoutInitiatorRequestTest.java    | 26 ++++--
 .../profile/impl/ProcessLogoutRequestTest.java     | 52 ++++++------
 10 files changed, 251 insertions(+), 177 deletions(-)

diff --git a/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SessionDataSupport.java b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SessionDataSupport.java
new file mode 100644
index 0000000..570403c
--- /dev/null
+++ b/sp-saml-api/src/main/java/net/shibboleth/sp/saml/saml2/SessionDataSupport.java
@@ -0,0 +1,97 @@
+/*
+ * 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;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.io.MarshallingException;
+import org.opensaml.core.xml.io.UnmarshallingException;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.saml.saml2.core.NameID;
+
+import net.shibboleth.shared.codec.Base64Support;
+import net.shibboleth.shared.codec.DecodingException;
+import net.shibboleth.shared.codec.EncodingException;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.xml.ParserPool;
+import net.shibboleth.shared.xml.SerializeSupport;
+import net.shibboleth.shared.xml.XMLParserException;
+
+/**
+ * Helper class encapsulating the creation and parsing of the opaque session data
+ * for SAML sessions, which consists of a {@link NameID} object.
+ */
+public final class SessionDataSupport {
+
+    /** DOM configuration parameters used by LSSerializer to exclude XML declaration. */
+    @Nonnull private static final Map<String, Object> NO_XML_DECL_PARAMS;
+        
+    /**
+     * Encode a {@link NameID} for preservation as a {@link String}.
+     * 
+     * @param nameID the object to peserve
+     * 
+     * @return the encoded object or null
+     * 
+     * @throws MarshallingException if unable to marshall the object into XML 
+     * @throws EncodingException if unable to encode the XML
+     */
+    @Nullable static public String preserveSessionData(@Nonnull final NameID nameID) throws MarshallingException, EncodingException {
+        final String xml = SerializeSupport.nodeToString(XMLObjectSupport.marshall(nameID), NO_XML_DECL_PARAMS);
+        return Base64Support.encodeURLSafe(xml.getBytes(StandardCharsets.UTF_8));
+    }
+
+    /**
+     * Recover a {@link NameID} from a {@link String} created by the {@link #preserveSessionData(NameID)}
+     * method.
+     * 
+     * @param parserPool XML parser to use 
+     * @param sessionData encoded data
+     * 
+     * @return recovered object or null
+     * 
+     * @throws DecodingException if unable to decode the string
+     * @throws IOException if unable to process the resulting data
+     * @throws UnmarshallingException if unable to unmarshall the XML
+     * @throws XMLParserException  if the parse fails or the data is of an incorrect type
+     */
+    @Nullable static public NameID recoverSessionData(@Nonnull final ParserPool parserPool,
+            @Nonnull final String sessionData) throws DecodingException, IOException, XMLParserException,
+                UnmarshallingException {
+        
+        final byte[] bytes = Base64Support.decodeURLSafe(sessionData);
+        
+        try (final InputStream source = new ByteArrayInputStream(bytes)) {
+            final XMLObject xmlObject = XMLObjectSupport.unmarshallFromInputStream(parserPool, source);
+            if (xmlObject instanceof NameID n) {
+                return n;
+            } else {
+                throw new XMLParserException("Decoded object was of unexpected type.");
+            }
+        }
+    }
+
+    static {
+        NO_XML_DECL_PARAMS = CollectionSupport.<String,Object>singletonMap("xml-declaration", Boolean.FALSE);
+    }
+}
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 0bbebd7..df929a0 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
@@ -97,6 +97,7 @@ import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
 import net.shibboleth.sp.messaging.RemotedHttpServletResponse;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.saml.saml2.SAMLStateData;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.profile.impl.PrepareAgentResponse;
 import net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutRequest;
 import net.shibboleth.sp.saml.saml2.profile.impl.ProcessLogoutResponse;
@@ -286,10 +287,10 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
         final LogoutRequest request = buildLogoutRequest(ISSUER);
         sign(request);
         final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='" + ISSUER
-                + "'>jdoe at example.org</NameID>";
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe at example.org");
+        nameID.setSPProvidedID(ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         setApplicationRequest(APPLICATION_ID, input);
         
         validateLogoutRequestResult(false);
@@ -304,10 +305,11 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
     public void testRequestUnsigned() throws Exception {
         final LogoutRequest request = buildLogoutRequest(ISSUER);
         final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='"
-                + NameIDType.EMAIL + "' SPProvidedID='" + ISSUER + "'>jdoe at example.org</NameID>";
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe at example.org");
+        nameID.setFormat(NameIDType.EMAIL);
+        nameID.setSPProvidedID(ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         setApplicationRequest(APPLICATION_ID, input);
         
         validateError(EventIds.INVALID_MESSAGE);
@@ -323,10 +325,11 @@ public class SAML2LogoutConsumerFlowTest extends AbstractSPFlowTest {
         final LogoutRequest request = buildLogoutRequest(ISSUER);
         sign(request);
         final DDF input = buildRemotedPOSTMessage(request, RELAY_STATE, null);
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='"
-                + NameIDType.EMAIL + "' SPProvidedID='" + ISSUER + "'>jdoe at example.org</NameID>";
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe at example.org");
+        nameID.setFormat(NameIDType.EMAIL);
+        nameID.setSPProvidedID(ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         setApplicationRequest(APPLICATION_ID, input);
         
         validateLogoutRequestResult(true);
diff --git a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutInitiatorFlowTest.java b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutInitiatorFlowTest.java
index 3451adc..478c2fd 100644
--- a/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutInitiatorFlowTest.java
+++ b/sp-saml-conf-impl/src/test/java/net/shibboleth/sp/saml/flows/saml2/SAML2LogoutInitiatorFlowTest.java
@@ -34,6 +34,7 @@ import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.SessionIndex;
+import org.opensaml.saml.saml2.testing.SAML2ActionTestingSupport;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.web.WebAppConfiguration;
@@ -55,6 +56,7 @@ import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
 import net.shibboleth.sp.messaging.RemotedHttpServletResponse;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.profile.SPConstants;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.profile.impl.PrepareAgentResponse;
 
 /**
@@ -84,20 +86,16 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     @Nonnull public static final byte[] RESOURCE_URL = "https://sp.example.org/secure".getBytes(StandardCharsets.UTF_8);
 
     /** Opaque session blob with index. */
-    @Nonnull public static final String SESSION_DATA =
-            "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://idp.example.org!!12345'>foo</NameID>";
+    @Nonnull public static final String SESSION_DATA = "https://idp.example.org!!12345";
 
     /** Opaque session blob. */
-    @Nonnull public static final String SESSION_DATA_NO_INDEX =
-            "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://idp.example.org'>foo</NameID>";
+    @Nonnull public static final String SESSION_DATA_NO_INDEX = "https://idp.example.org";
     
     /** Opaque session blob for no-endpoint IdP. */
-    @Nonnull public static final String SESSION_DATA_NO_ENDPOINT =
-            "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://noendpoint.example.org!!12345'>foo</NameID>";
+    @Nonnull public static final String SESSION_DATA_NO_ENDPOINT = "https://noendpoint.example.org!!12345";
 
     /** Opaque session blob for no-metadata IdP. */
-    @Nonnull public static final String SESSION_DATA_NO_METADATA =
-            "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://unknown.example.org!!12345'>foo</NameID>";
+    @Nonnull public static final String SESSION_DATA_NO_METADATA = "https://unknown.example.org!!12345";
     
     /** Constructor. */
     protected SAML2LogoutInitiatorFlowTest() {
@@ -107,14 +105,19 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     /**
      * Test flow with unverified (no metadata) IdP specified.
      * 
-     * @throws IOException 
+     * @throws Exception 
      */
     @Test
-    public void testUnverified() throws IOException {
+    public void testUnverified() throws Exception {
         setDefaultAuth();
+
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID(SESSION_DATA_NO_METADATA);
         
         final DDF input = new DDF(null).structure();
-        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(SESSION_DATA_NO_METADATA);
+        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
+                SessionDataSupport.preserveSessionData(nameID));
         input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
         input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
         setApplicationRequest("no-metadata", input);
@@ -128,14 +131,19 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     /**
      * Test flow with profile disallowed.
      * 
-     * @throws IOException 
+     * @throws Exception 
      */
     @Test
-    public void testProfileDisabled() throws IOException {
+    public void testProfileDisabled() throws Exception {
         setDefaultAuth();
+
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID(SESSION_DATA);
         
         final DDF input = new DDF(null).structure();
-        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(SESSION_DATA);
+        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
+                SessionDataSupport.preserveSessionData(nameID));
         input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
         input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
         setApplicationRequest("no-profile", input);
@@ -149,14 +157,19 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     /**
      * Test flow with no valid endpoint
      * 
-     * @throws IOException 
+     * @throws Exception 
      */
     @Test
-    public void testNoEndpoint() throws IOException {
+    public void testNoEndpoint() throws Exception {
         setDefaultAuth();
+        
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID(SESSION_DATA_NO_ENDPOINT);
 
         final DDF input = new DDF(null).structure();
-        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(SESSION_DATA_NO_ENDPOINT);
+        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
+                SessionDataSupport.preserveSessionData(nameID));
         input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
         input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
         setApplicationRequest("no-endpoint", input);
@@ -213,15 +226,19 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     /**
      * Test simple success case with encryption enabled.
      * 
-     * @throws IOException 
-     * @throws MessageDecodingException 
+     * @throws Exception 
      */
     @Test
-    public void testSimpleWithEncryption() throws IOException, MessageDecodingException {
+    public void testSimpleWithEncryption() throws Exception {
         setDefaultAuth();
         
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID(SESSION_DATA);
+        
         final DDF input = new DDF(null).structure();
-        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(SESSION_DATA);
+        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
+                SessionDataSupport.preserveSessionData(nameID));
         input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
         input.addmember(SPConstants.TARGET).unsafe_string(RESOURCE_URL);
         setApplicationRequest("logout-encryption", input);
@@ -237,15 +254,19 @@ public class SAML2LogoutInitiatorFlowTest extends AbstractSPFlowTest {
     /**
      * Test simple success case with computed relay state.
      * 
-     * @throws IOException 
-     * @throws MessageDecodingException 
+     * @throws Exception 
      */
     @Test
-    public void testSimple() throws IOException, MessageDecodingException {
+    public void testSimple() throws Exception {
         setDefaultAuth();
         
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID(SESSION_DATA);
+        
         final DDF input = new DDF(null).structure();
-        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(SESSION_DATA);
+        input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
+                SessionDataSupport.preserveSessionData(nameID));
         input.addmember(RemotedHttpServletRequest.STRUCTURE_NAME).structure();
         input.addmember(SPConstants.TARGET).unsafe_string("https://sp.example.org/cgi-bin/test.cgi?foo=bar%20baz&frobnitz=zorkmid".getBytes(StandardCharsets.UTF_8));
         
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 41ad705..9426acc 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
@@ -13,8 +13,6 @@
  */
 
 package net.shibboleth.sp.saml.flows.saml2;
-
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -26,7 +24,6 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.opensaml.core.xml.XMLObject;
 import org.opensaml.core.xml.io.MarshallingException;
 import org.opensaml.core.xml.io.UnmarshallingException;
 import org.opensaml.core.xml.util.XMLObjectSupport;
@@ -106,6 +103,7 @@ import net.shibboleth.sp.messaging.RemotedHttpServletRequest;
 import net.shibboleth.sp.messaging.RemotedHttpServletResponse;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.saml.saml2.SAMLStateData;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.profile.impl.PrepareAgentResponse;
 import net.shibboleth.sp.state.StateData;
 import net.shibboleth.sp.state.impl.CookieStateManager;
@@ -692,10 +690,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     /**
      * Test successful flow.
      * 
-     * @throws IOException 
+     * @throws Exception 
      */
     @Test
-    public void testSuccess() throws IOException {
+    public void testSuccess() throws Exception {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         sign(response);
         final DDF input = buildRemotedPOSTResponse(response, null, null);
@@ -714,11 +712,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     /**
      * Test successful flow with InResponseTo available.
      * 
-     * @throws IOException
-     * @throws ResolverException 
+     * @throws Exception
      */
     @Test
-    public void testSuccessWithState() throws IOException, ResolverException {
+    public void testSuccessWithState() throws Exception {
         
         final StateData data = buildStateData("foo");
         data.setAcrs(CollectionSupport.singletonList(AuthnContext.PPT_AUTHN_CTX));
@@ -743,10 +740,10 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
     /**
      * Test successful flow with attributes.
      * 
-     * @throws IOException 
+     * @throws Exception 
      */
     @Test
-    public void testSuccessAttributes() throws IOException {
+    public void testSuccessAttributes() throws Exception {
         final Response response = buildSAMLResponse(ISSUER, StatusCode.SUCCESS, null);
         final AttributeStatement statement = SAML2ActionTestingSupport.buildAttributeStatement();
         statement.getAttributes().add(
@@ -779,9 +776,14 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
      * @param sessionIndex SessionIndex from assertion
      * 
      * @return the output object
+     * 
+     * @throws UnmarshallingException 
+     * @throws XMLParserException 
+     * @throws IOException 
+     * @throws DecodingException 
      */
     @Nonnull private DDF validateOutputMessage(@Nonnull final FlowExecutionResult result,
-            @Nullable final Set<String> attributeIds, @Nullable final String resource, @Nullable final String sessionIndex) {
+            @Nullable final Set<String> attributeIds, @Nullable final String resource, @Nullable final String sessionIndex) throws DecodingException, IOException, XMLParserException, UnmarshallingException {
         final ProfileRequestContext prc = retrieveProfileRequestContext(result);
         assert prc != null;
         final AgentRequestContext arc = prc.ensureSubcontext(AgentRequestContext.class);
@@ -816,28 +818,14 @@ public class SAML2TokenConsumerFlowTest extends AbstractSPFlowTest {
         }
         Assert.assertTrue(mutableIds.isEmpty());
         
-        try {
-            final DDF s = output.getmember(ConsumerConstants.SESSION_OPAQUE);
-            assert s != null;
-            Assert.assertTrue(s.isstruct());
-            final DDF nameIdDdf = s.getmember(PrepareAgentResponse.NAMEID_PARAM);
-            Assert.assertTrue(nameIdDdf.isstring());
-            final String nameIdString = nameIdDdf.string();
-            assert nameIdString != null;
-            final byte[] opaque = Base64Support.decodeURLSafe(nameIdString);
-            try (final ByteArrayInputStream in = new ByteArrayInputStream(opaque)) {
-                final XMLObject obj = XMLObjectSupport.unmarshallFromInputStream(parserPool, in);
-                if (obj instanceof final NameID nameID) {
-                    Assert.assertEquals(nameID.getValue(), "jdoe at example.org");
-                    Assert.assertEquals(nameID.getFormat(), NameIDType.EMAIL);
-                    Assert.assertEquals(nameID.getSPProvidedID(), ISSUER + "!!" + sessionIndex);
-                } else {
-                    Assert.fail("Session data was not a NameID");
-                }
-            }
-        } catch (final DecodingException|IOException|UnmarshallingException|XMLParserException e) {
-            Assert.fail(e.getMessage());
-        }
+        final String nameIdString =
+                output.getmember(ConsumerConstants.SESSION_OPAQUE).getmember(PrepareAgentResponse.NAMEID_PARAM).string();
+        assert nameIdString != null;
+        final NameID nameID = SessionDataSupport.recoverSessionData(parserPool, nameIdString);
+        assert nameID != null;
+        Assert.assertEquals(nameID.getValue(), "jdoe at example.org");
+        Assert.assertEquals(nameID.getFormat(), NameIDType.EMAIL);
+        Assert.assertEquals(nameID.getSPProvidedID(), ISSUER + "!!" + sessionIndex);
         
         return output;
     }
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponse.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponse.java
index 77d67da..7105d53 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponse.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponse.java
@@ -14,16 +14,13 @@
 
 package net.shibboleth.sp.saml.saml2.profile.impl;
 
-import java.nio.charset.StandardCharsets;
 import java.time.Instant;
-import java.util.Map;
 import java.util.function.Function;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.core.xml.util.XMLObjectSupport;
 import org.opensaml.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
@@ -38,14 +35,12 @@ import org.slf4j.Logger;
 import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
 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;
 import net.shibboleth.shared.logic.Constraint;
 import net.shibboleth.shared.primitive.LoggerFactory;
-import net.shibboleth.shared.xml.SerializeSupport;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.AbstractTokenConsumerResponseAction;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.context.SAMLTokenContext;
 
 /**
@@ -67,9 +62,6 @@ public class PrepareAgentResponse extends AbstractTokenConsumerResponseAction {
     /** Parameter for accessing NameID from opaque data. */
     @Nonnull @NotEmpty public static final String NAMEID_PARAM = "NameID";
     
-    /** DOM configuration parameters used by LSSerializer to exclude XML declaration. */
-    @Nonnull private static final Map<String, Object> NO_XML_DECL_PARAMS;
-    
     /** Class logger. */
     @Nonnull private Logger log = LoggerFactory.getLogger(PrepareAgentResponse.class);
 
@@ -142,10 +134,9 @@ public class PrepareAgentResponse extends AbstractTokenConsumerResponseAction {
         }
         
         try {
-            final String xml = SerializeSupport.nodeToString(XMLObjectSupport.marshall(nameID), NO_XML_DECL_PARAMS);
-            return new DDF(NAMEID_PARAM).string(Base64Support.encodeURLSafe(xml.getBytes(StandardCharsets.UTF_8)));
+            return new DDF(NAMEID_PARAM).string(SessionDataSupport.preserveSessionData(nameID));
         } catch (final MarshallingException | EncodingException e) {
-            log.error("{} Error marshalling and encoding NameID", getLogPrefix(), e);
+            log.error("{} Error preserving NameID", getLogPrefix(), e);
         }
         
         return null;
@@ -157,9 +148,5 @@ public class PrepareAgentResponse extends AbstractTokenConsumerResponseAction {
         final AuthnStatement statement = samlTokenContext.getAuthnStatement();
         return statement != null ? statement.getSessionNotOnOrAfter() : null;
     }    
-
-    static {
-        NO_XML_DECL_PARAMS = CollectionSupport.<String,Object>singletonMap("xml-declaration", Boolean.FALSE);
-    }
-
+    
 }
\ No newline at end of file
diff --git a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequest.java b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequest.java
index 633efa4..752ee31 100644
--- a/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequest.java
+++ b/sp-saml-impl/src/main/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequest.java
@@ -14,15 +14,13 @@
 
 package net.shibboleth.sp.saml.saml2.profile.impl;
 
-import java.io.StringReader;
+import java.io.IOException;
 import java.util.function.Function;
 
 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.messaging.context.navigate.ChildContextLookup;
 import org.opensaml.profile.action.ActionSupport;
 import org.opensaml.profile.action.EventIds;
@@ -36,11 +34,13 @@ import net.shibboleth.shared.xml.XMLParserException;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.AbstractApplicationAction;
 import net.shibboleth.sp.profile.ConsumerConstants;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.context.SAMLLogoutContext;
 import net.shibboleth.idp.profile.IdPEventIds;
 import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+import net.shibboleth.shared.codec.DecodingException;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
 
@@ -144,25 +144,20 @@ public class ProcessLogoutInitiatorRequest extends AbstractApplicationAction {
         
         // Decode NameID from session data from Agent and unpack the buried information.
         try {
-            final XMLObject xmlObject = XMLObjectSupport.unmarshallFromReader(parserPool, new StringReader(pickled));
-            if (xmlObject instanceof NameID n) {
-                final String buriedData = n.getSPProvidedID();
-                if (buriedData != null) {
-                    final int index = buriedData.indexOf("!!");
-                    if (index > 0) {
-                        relyingPartyId = buriedData.substring(0, index);
-                        sessionIndex = buriedData.substring(index + 2);
-                    } else {
-                        relyingPartyId = buriedData;
-                    }
-                    nameID = n;
+            nameID = SessionDataSupport.recoverSessionData(parserPool, pickled);
+            final String buriedData = nameID.getSPProvidedID();
+            if (buriedData != null) {
+                final int index = buriedData.indexOf("!!");
+                if (index > 0) {
+                    relyingPartyId = buriedData.substring(0, index);
+                    sessionIndex = buriedData.substring(index + 2);
                 } else {
-                    throw new XMLParserException("Decoded NameID did not contain required data for logout.");
+                    relyingPartyId = buriedData;
                 }
             } else {
-                throw new XMLParserException("Decoded object was of unexpected type.");
+                throw new XMLParserException("Decoded NameID did not contain required data for logout.");
             }
-        } catch (final XMLParserException | UnmarshallingException e) {
+        } catch (final XMLParserException | UnmarshallingException | DecodingException | IOException e) {
             ActionSupport.buildEvent(profileRequestContext, EventIds.UNABLE_TO_DECODE);
             log.error("{} Failed to decode session information", getLogPrefix(), e);
             return false;
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 3944022..d0e5070 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
@@ -51,6 +51,7 @@ import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.AbstractApplicationAction;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.saml.saml2.SAMLStateData;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.state.StateManager;
 import net.shibboleth.profile.context.navigate.IssuerLookupFunction;
 import net.shibboleth.profile.context.navigate.RelyingPartyIdLookupFunction;
@@ -259,15 +260,7 @@ public class ProcessLogoutRequest extends AbstractApplicationAction {
         // Decode NameID from session data from Agent and unpack the buried information.
         NameID sessionNameID = null;
         try {
-            final byte[] bytes = Base64Support.decodeURLSafe(pickled);
-            try (final InputStream source = new ByteArrayInputStream(bytes)) {
-                final XMLObject xmlObject = XMLObjectSupport.unmarshallFromInputStream(parserPool, source);
-                if (xmlObject instanceof NameID n) {
-                    sessionNameID = n;
-                } else {
-                    throw new XMLParserException("Decoded object was of unexpected type.");
-                }
-            }
+            sessionNameID = SessionDataSupport.recoverSessionData(parserPool, pickled);
         } catch (final DecodingException | IOException | XMLParserException | UnmarshallingException e) {
             log.warn("{} Failed to decode session information", getLogPrefix(), e);
         }
diff --git a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponseTest.java b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponseTest.java
index 500cdaf..707aa9b 100644
--- a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponseTest.java
+++ b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/PrepareAgentResponseTest.java
@@ -14,17 +14,11 @@
 
 package net.shibboleth.sp.saml.saml2.profile.impl;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 
 import javax.annotation.Nonnull;
 
-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;
 import org.opensaml.saml.saml2.core.Assertion;
 import org.opensaml.saml.saml2.core.AuthnStatement;
@@ -46,16 +40,15 @@ import net.shibboleth.idp.attribute.context.AttributeContext;
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.codec.DecodingException;
 import net.shibboleth.shared.codec.EncodingException;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.xml.XMLParserException;
 import net.shibboleth.shared.xml.impl.BasicParserPool;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.messaging.RemotedHttpServletResponse;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.profile.impl.BaseApplicationActionTest;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.context.SAMLTokenContext;
 
 /**
@@ -133,12 +126,10 @@ public class PrepareAgentResponseTest extends BaseApplicationActionTest {
     /**
      * Unit test for opaque session blob.
      * 
-     * @throws DecodingException 
-     * @throws IOException 
-     * @throws ComponentInitializationException 
+     * @throws Exception 
      */
     @Test
-    public void testSessionState() throws DecodingException, IOException, ComponentInitializationException {
+    public void testSessionState() throws Exception {
         buildAssertion();
         
         final Event event = action.execute(src);
@@ -150,28 +141,15 @@ public class PrepareAgentResponseTest extends BaseApplicationActionTest {
         
         final DDF state = out.getmember(ConsumerConstants.SESSION_OPAQUE);        
         Assert.assertTrue(state.isstruct());
-        final DDF nameId = state.getmember(PrepareAgentResponse.NAMEID_PARAM);
-        Assert.assertTrue(nameId.isstring());
+        final String nameIdString = state.getmember(PrepareAgentResponse.NAMEID_PARAM).string();
+        assert nameIdString != null;
         
-        final String encoded = nameId.string();
-        assert encoded != null;
-        final byte[] decoded = Base64Support.decodeURLSafe(encoded);
-
-        try (final InputStream in = new ByteArrayInputStream(decoded)) {
-            final BasicParserPool parserPool = new BasicParserPool();
-            parserPool.initialize();
-            final XMLObject xmlobj =
-                    XMLObjectSupport.unmarshallFromInputStream(parserPool, in);
-            parserPool.destroy();
-            if (xmlobj instanceof final NameID nameID) {
-                Assert.assertEquals(nameID.getValue(), "jdoe");
-                Assert.assertEquals(nameID.getSPProvidedID(), "foo!!foo");
-            } else {
-                Assert.fail("XMLObject stored in NameID field was not a NameID");
-            }
-        } catch (final XMLParserException | UnmarshallingException e) {
-            Assert.fail("Unable to parse or unmarshall NameID", e);
-        }
+        final BasicParserPool pool = new BasicParserPool();
+        pool.initialize();
+        final NameID nameID = SessionDataSupport.recoverSessionData(pool, nameIdString);
+        assert nameID != null;
+        Assert.assertEquals(nameID.getValue(), "jdoe");
+        Assert.assertEquals(nameID.getSPProvidedID(), "foo!!foo");
     }
 
     /**
diff --git a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequestTest.java b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequestTest.java
index b292ce2..1cd8743 100644
--- a/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequestTest.java
+++ b/sp-saml-impl/src/test/java/net/shibboleth/sp/saml/saml2/profile/impl/ProcessLogoutInitiatorRequestTest.java
@@ -17,6 +17,7 @@ package net.shibboleth.sp.saml.saml2.profile.impl;
 
 import org.opensaml.profile.action.EventIds;
 import org.opensaml.saml.saml2.core.NameID;
+import org.opensaml.saml.saml2.testing.SAML2ActionTestingSupport;
 import org.springframework.webflow.execution.Event;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
@@ -30,6 +31,7 @@ import net.shibboleth.shared.xml.impl.BasicParserPool;
 import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.profile.impl.BaseApplicationActionTest;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.saml.saml2.context.SAMLLogoutContext;
 
 /**
@@ -112,10 +114,12 @@ public class ProcessLogoutInitiatorRequestTest extends BaseApplicationActionTest
     }
 
     @Test
-    public void testIncompleteSessionData() throws ComponentInitializationException {
+    public void testIncompleteSessionData() throws Exception {
         final DDF input = new DDF(null).structure();
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar'>foo</NameID>");
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -124,10 +128,13 @@ public class ProcessLogoutInitiatorRequestTest extends BaseApplicationActionTest
     }
 
     @Test
-    public void testNoIndex() throws ComponentInitializationException {
+    public void testNoIndex() throws Exception {
         final DDF input = new DDF(null).structure();
+        NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID("https://idp.example.org/idp");
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://idp.example.org/idp'>foo</NameID>");
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -138,7 +145,7 @@ public class ProcessLogoutInitiatorRequestTest extends BaseApplicationActionTest
         assert logoutContext != null;
         Assert.assertNull(logoutContext.getSessionIndex());
         
-        final NameID nameID = logoutContext.getNameID();
+        nameID = logoutContext.getNameID();
         assert nameID != null;
         Assert.assertEquals(nameID.getValue(), "foo");
         Assert.assertEquals(nameID.getFormat(), "bar");
@@ -146,10 +153,13 @@ public class ProcessLogoutInitiatorRequestTest extends BaseApplicationActionTest
     }
 
     @Test
-    public void testIndex() throws ComponentInitializationException {
+    public void testIndex() throws Exception {
         final DDF input = new DDF(null).structure();
+        NameID nameID = SAML2ActionTestingSupport.buildNameID("foo");
+        nameID.setFormat("bar");
+        nameID.setSPProvidedID("https://idp.example.org/idp!!12345");
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar' SPProvidedID='https://idp.example.org/idp!!12345'>foo</NameID>");
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -160,7 +170,7 @@ public class ProcessLogoutInitiatorRequestTest extends BaseApplicationActionTest
         assert logoutContext != null;
         Assert.assertEquals(logoutContext.getSessionIndex(), "12345");
         
-        final NameID nameID = logoutContext.getNameID();
+        nameID = logoutContext.getNameID();
         assert nameID != null;
         Assert.assertEquals(nameID.getValue(), "foo");
         Assert.assertEquals(nameID.getFormat(), "bar");
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 f060822..43b2c1a 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
@@ -16,7 +16,6 @@ package net.shibboleth.sp.saml.saml2.profile.impl;
 
 
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 
 import javax.annotation.Nonnull;
@@ -31,6 +30,7 @@ import org.opensaml.saml.saml2.core.Extensions;
 import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.LogoutRequest;
 import org.opensaml.saml.saml2.core.LogoutResponse;
+import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.RequestAbstractType;
 import org.opensaml.saml.saml2.core.SessionIndex;
 import org.opensaml.saml.saml2.testing.SAML2ActionTestingSupport;
@@ -48,8 +48,6 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 
 import net.shibboleth.idp.profile.testing.ActionTestingSupport;
 import net.shibboleth.profile.context.RelyingPartyContext;
-import net.shibboleth.shared.codec.Base64Support;
-import net.shibboleth.shared.codec.EncodingException;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.resource.Resource;
 import net.shibboleth.shared.security.DataSealer;
@@ -59,6 +57,7 @@ import net.shibboleth.sp.ddf.DDF;
 import net.shibboleth.sp.profile.ConsumerConstants;
 import net.shibboleth.sp.profile.impl.BaseApplicationActionTest;
 import net.shibboleth.sp.saml.saml2.SAMLStateData;
+import net.shibboleth.sp.saml.saml2.SessionDataSupport;
 import net.shibboleth.sp.state.impl.PassthroughStateManager;
 import net.shibboleth.sp.testing.TestResourceConverter;
 
@@ -191,13 +190,14 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
     
     @Test
-    public void testExpired() throws IOException {
+    public void testExpired() throws Exception {
         ((LogoutRequest) prc.ensureInboundMessageContext().ensureMessage()).setNotOnOrAfter(Instant.now().minusSeconds(300));
 
         final DDF input = new DDF(null).structure();
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setSPProvidedID(ActionTestingSupport.INBOUND_MSG_ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='"
-                        + ActionTestingSupport.INBOUND_MSG_ISSUER + "'>jdoe</NameID>");
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
         
         final Event event = action.execute(src);
@@ -251,11 +251,13 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testIncompleteSessionData() throws IOException, EncodingException {
+    public void testIncompleteSessionData() throws Exception {
         final DDF input = new DDF(null).structure();
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' Format='bar'>foo</NameID>"; 
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setFormat("bar");
+        
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -268,12 +270,12 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testMatchNoIndex() throws IOException, EncodingException {
+    public void testMatchNoIndex() throws Exception {
         final DDF input = new DDF(null).structure();
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='"
-                + ActionTestingSupport.INBOUND_MSG_ISSUER + "'>jdoe</NameID>"; 
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setSPProvidedID(ActionTestingSupport.INBOUND_MSG_ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final Event event = action.execute(src);
@@ -286,12 +288,12 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testNoMatchWithIndex() throws IOException, EncodingException {
+    public void testNoMatchWithIndex() throws Exception {
         final DDF input = new DDF(null).structure();
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='"
-                + ActionTestingSupport.INBOUND_MSG_ISSUER + "!!12345'>jdoe</NameID>"; 
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setSPProvidedID(ActionTestingSupport.INBOUND_MSG_ISSUER + "!!12345");
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final SAMLObjectBuilder<SessionIndex> indexBuilder = (SAMLObjectBuilder<SessionIndex>)
@@ -315,12 +317,12 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testMatchWithIndex() throws IOException, EncodingException {
+    public void testMatchWithIndex() throws Exception {
         final DDF input = new DDF(null).structure();
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='"
-                + ActionTestingSupport.INBOUND_MSG_ISSUER + "!!12345'>jdoe</NameID>"; 
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setSPProvidedID(ActionTestingSupport.INBOUND_MSG_ISSUER + "!!12345");
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final SAMLObjectBuilder<SessionIndex> indexBuilder = (SAMLObjectBuilder<SessionIndex>)
@@ -340,12 +342,12 @@ public class ProcessLogoutRequestTest extends BaseApplicationActionTest {
     }
     
     @Test
-    public void testMatchAsynch() throws IOException, EncodingException {
+    public void testMatchAsynch() throws Exception {
         final DDF input = new DDF(null).structure();
-        final String opaque = "<NameID xmlns='urn:oasis:names:tc:SAML:2.0:assertion' SPProvidedID='"
-                + ActionTestingSupport.INBOUND_MSG_ISSUER + "'>jdoe</NameID>"; 
+        final NameID nameID = SAML2ActionTestingSupport.buildNameID("jdoe");
+        nameID.setSPProvidedID(ActionTestingSupport.INBOUND_MSG_ISSUER);
         input.addmember(ConsumerConstants.SESSION_OPAQUE).addmember(PrepareAgentResponse.NAMEID_PARAM).string(
-                Base64Support.encodeURLSafe(opaque.getBytes(StandardCharsets.UTF_8)));
+                SessionDataSupport.preserveSessionData(nameID));
         arc.setInput(input);
 
         final SAMLObjectBuilder<Extensions> extsBuilder = (SAMLObjectBuilder<Extensions>)

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


More information about the commits mailing list