[java-plugin-shibd] branch dev/StateMgmtWIP updated: Bug fix and unit test for sealed state manager case.

Codeberg noreply at shibboleth.net
Tue May 5 13:02:30 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.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/1c1096293c6a3406fb739991a98187509bed46cf

The following commit(s) were added to refs/heads/dev/StateMgmtWIP by this push:
     new 1c10962  Bug fix and unit test for sealed state manager case.
1c10962 is described below

commit 1c1096293c6a3406fb739991a98187509bed46cf
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue May 5 09:02:14 2026 -0400

    Bug fix and unit test for sealed state manager case.
---
 .../sp/state/impl/CookieStateManager.java          |  2 +-
 .../sp/state/impl/CookieStateManagerTest.java      | 94 ++++++++++++++++++----
 2 files changed, 80 insertions(+), 16 deletions(-)

diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/state/impl/CookieStateManager.java b/sp-server-impl/src/main/java/net/shibboleth/sp/state/impl/CookieStateManager.java
index 29f9875..d1fef30 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/state/impl/CookieStateManager.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/state/impl/CookieStateManager.java
@@ -144,12 +144,12 @@ public class CookieStateManager extends AbstractStateManager {
             } else {
                 try {
                     decoded = new String(Base64Support.decodeURLSafe(cookieValue), StandardCharsets.UTF_8);
-                    return decoded;
                 } catch (final DecodingException e) {
                     throw new IOException(e);
                 }
             }
             log.trace("Recovered state token mapping from '{}' to value '{}'", stateToken, decoded);
+            return decoded;
         }
 
         log.warn("No cookie found matching state token: '{}'", stateToken);
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/state/impl/CookieStateManagerTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/state/impl/CookieStateManagerTest.java
index 0cfa75c..9352e26 100644
--- a/sp-server-impl/src/test/java/net/shibboleth/sp/state/impl/CookieStateManagerTest.java
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/state/impl/CookieStateManagerTest.java
@@ -22,11 +22,11 @@ import java.util.List;
 
 import javax.annotation.Nonnull;
 
+import org.springframework.core.io.ClassPathResource;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
@@ -41,8 +41,12 @@ import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.net.CookieManager;
 import net.shibboleth.shared.net.CookieManager.SameSiteValue;
 import net.shibboleth.shared.primitive.NonnullSupplier;
+import net.shibboleth.shared.resource.Resource;
+import net.shibboleth.shared.security.DataSealer;
+import net.shibboleth.shared.security.impl.BasicKeystoreKeyStrategy;
 import net.shibboleth.sp.profile.impl.BaseApplicationActionTest;
 import net.shibboleth.sp.state.StateData;
+import net.shibboleth.sp.testing.TestResourceConverter;
 
 /**
  * Unit tests for {@link CookieStateManager}.
@@ -57,15 +61,17 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
     // Unicode character at the end of that filename...
     @Nonnull @NotEmpty private static final String TEST_RESOURCE = "https://sp.example.org/secure/foo☯.cgi";
     
+    private Resource keystoreResource;
+    private Resource versionResource;
+    
+    private DataSealer sealer;
     private CookieManager cookieManager;
     private CookieStateManager stateManager;
     
     private MockHttpServletRequest request;
     private MockHttpServletResponse response;
     
-    @BeforeClass
-    public void setUp() throws ComponentInitializationException {
-        
+    public void setUp(final boolean sealed) throws ComponentInitializationException {
         cookieManager = new CookieManager();
         cookieManager.setCookiePath("/");
         cookieManager.setSameSite(SameSiteValue.None);
@@ -83,30 +89,57 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
             }
         });
         cookieManager.initialize();
-        
+                
         stateManager = new CookieStateManager();
         stateManager.setId("test");
 
+        if (sealed) {
+            ClassPathResource resource =
+                    new ClassPathResource("/net/shibboleth/sp/profile/impl/SealerKeyStore.jks");
+            Assert.assertTrue(resource.exists());
+            keystoreResource = TestResourceConverter.of(resource);
+
+            resource =
+                    new ClassPathResource("/net/shibboleth/sp/profile/impl/SealerKeyStore.kver");
+            Assert.assertTrue(resource.exists());
+            versionResource = TestResourceConverter.of(resource);
+
+            final BasicKeystoreKeyStrategy strategy = new BasicKeystoreKeyStrategy();
+            strategy.setKeyAlias("secret");
+            strategy.setKeyPassword("kpassword");
+            strategy.setKeystorePassword("password");
+            strategy.setKeystoreResource(keystoreResource);
+            strategy.setKeyVersionResource(versionResource);
+            strategy.initialize();
+            
+            final DataSealer sealer = new DataSealer();
+            sealer.setKeyStrategy(strategy);
+            sealer.initialize();
+            
+            stateManager.setDataSealer(sealer);
+        }
+        
         final ObjectMapper mapper = new ObjectMapper();
         mapper.registerModule(new JavaTimeModule());
-        stateManager.setObjectMapper(mapper);
-        
+        stateManager.setObjectMapper(mapper);        
         stateManager.setHttpServletRequestSupplier(new NonnullSupplier<HttpServletRequest>() {
             @Nonnull public HttpServletRequest get() {
                 assert request != null;
                 return request;
             }
         });
-        
         stateManager.setCookieManager(cookieManager);
-        
         stateManager.initialize();
     }
-    
+
     @AfterClass
     public void tearDown() {
         stateManager.destroy();
         cookieManager.destroy();
+        if (sealer != null) {
+            sealer.destroy();
+        }
+        
     }
     
     @BeforeMethod
@@ -118,14 +151,17 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
     }
     
     @Test
-    public void testMissing() throws IOException {
+    public void testMissing() throws IOException, ComponentInitializationException {
+        setUp(false);
+        
         request.setCookies(new Cookie(getCookieName(), "foo"));
         
         Assert.assertNull(stateManager.recoverFromStateToken(agent, application, "foo", StateData.class));
     }
 
     @Test
-    public void testPurge() throws IOException, InterruptedException {
+    public void testPurge() throws IOException, InterruptedException, ComponentInitializationException {
+        setUp(false);
         
         final List<Cookie> cookies = new ArrayList<>(12);
         for (int i = 0; i < 12; ++i) {
@@ -145,7 +181,33 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testSuccess() throws IOException {
+    public void testSuccessSealed() throws IOException, ComponentInitializationException {
+        setUp(true);
+        
+        final StateData source = buildStateData();
+        final String token = stateManager.preserveToStateToken(agent, application, source);
+        assert token != null;
+        
+        // Move token set on response to request.
+        request = new MockHttpServletRequest();
+        request.setCookies(response.getCookies());
+        response = new MockHttpServletResponse();
+        
+        final StateData recovered = stateManager.recoverFromStateToken(agent, application, token, StateData.class);
+        Assert.assertEquals(source, recovered);
+        
+        // Check that old token is unset.
+        final Cookie[] cookies = response.getCookies();
+        Assert.assertEquals(cookies.length, 1);
+        Assert.assertEquals(cookies[0].getName(), CookieStateManager.DEFAULT_PREFIX + '_' + "default" + '_' + token);
+        Assert.assertEquals(cookies[0].getValue(), null);
+        Assert.assertEquals(cookies[0].getMaxAge(), 0);
+        Assert.assertEquals(cookies[0].getAttribute("SameSite"), SameSiteValue.None.getValue());
+    }
+    
+    @Test
+    public void testSuccess() throws IOException, ComponentInitializationException {
+        setUp(false);
         
         final StateData source = buildStateData();
         final String token = stateManager.preserveToStateToken(agent, application, source);
@@ -169,7 +231,8 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testSuccessWithAddress() throws IOException {
+    public void testSuccessWithAddress() throws IOException, ComponentInitializationException {
+        setUp(false);
         
         final StateData source = buildStateData();
         source.setClientAddress("192.168.1.1");
@@ -195,7 +258,8 @@ public class CookieStateManagerTest extends BaseApplicationActionTest {
     }
 
     @Test
-    public void testFailureWithAddress() throws IOException {
+    public void testFailureWithAddress() throws IOException, ComponentInitializationException {
+        setUp(false);
         
         final StateData source = buildStateData();
         source.setClientAddress("192.168.1.1");

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


More information about the commits mailing list