[java-plugin-shibd] branch main updated: Wire up new StateManager beans for eventual use in flows.

Codeberg noreply at shibboleth.net
Tue Apr 21 20:03:08 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.

View the commit online:
https://codeberg.org/Shibboleth/java-plugin-shibd/commit/91538f566281ee55df44099d4437b91c29f3c205

The following commit(s) were added to refs/heads/main by this push:
     new 91538f5  Wire up new StateManager beans for eventual use in flows.
91538f5 is described below

commit 91538f566281ee55df44099d4437b91c29f3c205
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Apr 21 16:02:54 2026 -0400

    Wire up new StateManager beans for eventual use in flows.
---
 .../shibboleth/idp/module/conf/sp/sp.properties    |  6 ++++
 .../net/shibboleth/sp/conf/agents-system.xml       | 33 ++++++++++++++++++++-
 ...SPEnvironmentApplicationContextInitializer.java |  4 +++
 .../shibboleth/sp/service/AgentResolverTest.java   |  1 +
 .../net/shibboleth/sp/service/utility.xml          | 13 +++++++++
 .../main/java/net/shibboleth/sp/Application.java   | 11 +++++++
 .../net/shibboleth/sp/impl/BasicApplication.java   | 34 ++++++++++++++++++++++
 7 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
index 492d79d..cf09a9f 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
@@ -31,6 +31,12 @@ sp.service.agents.checkInterval = PT5M
 #sp.stateToken.StorageService = shibboleth.StorageService
 # Cookie prefix when using cookie-backed state
 #sp.stateToken.cookiePrefix = __Host-shibsp_state_
+# Lifetime to preserve state before discarding
+#sp.stateToken.lifetime = PT30M
+# Whether to seal/encrypt data stored by state manager
+#sp.stateToken.sealed = true
+# Whether to check for replay of state tokens
+#sp.stateToken.checkReplay = false
 
 # Request/response correlation control
 #sp.correlation.cookiePrefix = __Host-shibsp_req_
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
index b704d0e..f24a6cc 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
@@ -63,13 +63,21 @@
         p:unverifiedConfiguration-ref="DefaultUnverifiedRelyingPartyConfiguration"
         p:relyingPartyConfigurations-ref="shibboleth.sp.RelyingPartyOverrides"
         p:discoveryServiceLookupStrategy="#{getObject('%{sp.discoveryURLFunction:DefaultDiscoveryServiceStrategy}'.trim())}"
-        p:stateTokenManager-ref="#{'%{sp.stateToken.Manager:shibboleth.sp.StorageStateTokenManager}'.trim()}" />
+        p:stateTokenManager-ref="#{'%{sp.stateToken.Manager:shibboleth.sp.CookieStateTokenManager}'.trim()}"
+        p:stateManager-ref="shibboleth.sp.CookieStateManager" />
+        <!--
+        // TODO: make this property-driven once we retire the older interface
+        
+        p:stateManager-ref="#{'%{sp.stateToken.Manager:shibboleth.sp.CookieStateManager}'.trim()}" />
+         -->
 
     <bean id="shibboleth.sp.Application" class="net.shibboleth.sp.impl.BasicApplication" abstract="true"
         p:metricName="net.shibboleth.sp.relyingparty.configurations" />
 
     <bean id="shibboleth.sp.PassthroughStateTokenManager" class="net.shibboleth.sp.impl.PassthroughStateTokenManager" lazy-init="true" />
 
+    <!-- Deprecated, will be removed once we redo the flows. -->
+
     <bean id="shibboleth.sp.StorageStateTokenManager" class="net.shibboleth.sp.impl.StorageServiceStateTokenManager" lazy-init="true"
         p:storageService-ref="#{'%{sp.stateToken.StorageService:shibboleth.StorageService}'.trim()}" />
 
@@ -77,6 +85,29 @@
         p:cookieManager-ref="shibboleth.sp.RemotedCookieManager"
         p:cookiePrefix="#{'%{sp.stateToken.cookiePrefix:__Host-shibsp_state_}'.trim()}" />
 
+    <!-- State Managers -->
+
+    <bean id="shibboleth.sp.StateManager" abstract="true"
+        p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier"
+        p:replayCache="#{%{sp.stateToken.checkReplay:false} ? getObject('shibboleth.ReplayCache') : null}"
+        p:dataSealer="#{%{sp.stateToken.sealed:true} ? (getObject('shibboleth.DataSealer') ?: 'Invalid') : null}"
+        p:objectMapper-ref="shibboleth.JSONObjectMapper"
+        p:expiration="%{sp.stateToken.lifetime:PT30M}" />
+
+    <bean id="shibboleth.sp.StorageOnlyStateManager" parent="shibboleth.sp.StateManager"
+        class="net.shibboleth.sp.state.impl.StorageServiceStateManager" lazy-init="true"
+        p:storageService-ref="#{'%{sp.stateToken.StorageService:shibboleth.StorageService}'.trim()}" />
+
+    <bean id="shibboleth.sp.StorageAndCookieStateManager" parent="shibboleth.sp.StorageOnlyStateManager"
+        class="net.shibboleth.sp.state.impl.StorageServiceStateManager" lazy-init="true"
+        p:cookieManager-ref="shibboleth.sp.RemotedCookieManager"
+        p:cookiePrefix="#{'%{sp.stateToken.cookiePrefix:__Host-shibsp_state_}'.trim()}" />
+
+    <bean id="shibboleth.sp.CookieStateManager" parent="shibboleth.sp.StateManager"
+        class="net.shibboleth.sp.state.impl.CookieStateManager" lazy-init="true"
+        p:cookieManager-ref="shibboleth.sp.RemotedCookieManager"
+        p:cookiePrefix="#{'%{sp.stateToken.cookiePrefix:__Host-shibsp_state_}'.trim()}" />
+
     <!-- More traditional beans akin to IdP service. -->
 
     <bean id="shibboleth.sp.DefaultSecurityConfiguration" class="org.opensaml.security.config.BasicSecurityConfiguration" />
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TestSPEnvironmentApplicationContextInitializer.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TestSPEnvironmentApplicationContextInitializer.java
index 31ecb19..c602e84 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TestSPEnvironmentApplicationContextInitializer.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/TestSPEnvironmentApplicationContextInitializer.java
@@ -33,6 +33,10 @@ public class TestSPEnvironmentApplicationContextInitializer extends TestEnvironm
      */
     protected void addProperties(@Nonnull final MockPropertySource mock) {
         super.addProperties(mock);
+        
+        // Avoids some complex mocking for the default StateManager bean.
+        mock.setProperty("sp.stateToken.sealed", "false");
+        
         mock.setProperty("sp.storageService", "shibboleth.StorageService");
         mock.setProperty("sp.session.storageService", "shibboleth.StorageService");
         mock.setProperty("idp.additionalProperties",
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
index 24d6f43..e9c9cb7 100644
--- a/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/service/AgentResolverTest.java
@@ -304,6 +304,7 @@ public class AgentResolverTest extends AbstractTestNGSpringContextTests {
             final Properties props = new Properties();
             try (final InputStream in = resource.getInputStream()) {
                 props.load(in);
+                props.setProperty("sp.stateToken.sealed", "false");
             } catch (IOException e) {
                 Assert.fail(e.getMessage());
             }
diff --git a/sp-conf-impl/src/test/resources/net/shibboleth/sp/service/utility.xml b/sp-conf-impl/src/test/resources/net/shibboleth/sp/service/utility.xml
index c3b0aef..cecbf8f 100644
--- a/sp-conf-impl/src/test/resources/net/shibboleth/sp/service/utility.xml
+++ b/sp-conf-impl/src/test/resources/net/shibboleth/sp/service/utility.xml
@@ -28,7 +28,20 @@
     <bean id="shibboleth.AttributeFilterService" class="net.shibboleth.shared.testing.MockReloadableService" />
     <bean id="shibboleth.AttributeRegistryService" class="net.shibboleth.shared.testing.MockReloadableService" />
 
+    <!--  Used for mocking AgentResolver's state manager beans. -->
+
     <bean id="shibboleth.StorageService"
         class="org.opensaml.storage.impl.MemoryStorageService" />
 
+    <bean id="shibboleth.RemotedHttpServletRequestSupplier"
+        class="net.shibboleth.sp.messaging.impl.RemotedHttpServletRequestSupplier" />
+    <bean id="shibboleth.RemotedHttpServletResponseSupplier"
+        class="net.shibboleth.sp.messaging.impl.RemotedlHttpServletResponseSupplier" />
+
+    <bean id="shibboleth.JSONObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
+
+    <bean id="shibboleth.sp.RemotedCookieManager" class="net.shibboleth.shared.net.CookieManager"
+        p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier"
+        p:httpServletResponseSupplier-ref="shibboleth.RemotedHttpServletResponseSupplier" />
+
 </beans>
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/Application.java b/sp-server-api/src/main/java/net/shibboleth/sp/Application.java
index bbe3915..34901c9 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/Application.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/Application.java
@@ -31,6 +31,7 @@ import net.shibboleth.profile.relyingparty.RelyingPartyConfigurationResolver;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.service.ReloadableService;
 import net.shibboleth.sp.profile.StateTokenManager;
+import net.shibboleth.sp.state.StateManager;
 
 /**
  * A collection of resources protected by the SP and treated as a unit for the purposes of
@@ -106,9 +107,19 @@ public interface Application extends RelyingPartyConfigurationResolver {
      * Gets the {@link StateTokenManager} to use for thie application.
      * 
      * @return the manager to use
+     * 
+     * @deprecated
      */
+    @Deprecated
     @Nonnull StateTokenManager getStateTokenManager();
 
+    /**
+     * Gets the {@link StateManager} to use for thie application.
+     * 
+     * @return the manager to use
+     */
+    @Nonnull StateManager getStateManager();
+    
     /**
      * Gets {@link AttributeTranscoderRegistry} for this {@link Application}.
      * 
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
index bb9c0d4..5f01f6f 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicApplication.java
@@ -59,6 +59,7 @@ import net.shibboleth.sp.Agent;
 import net.shibboleth.sp.Application;
 import net.shibboleth.sp.ProtocolSupportService;
 import net.shibboleth.sp.profile.StateTokenManager;
+import net.shibboleth.sp.state.StateManager;
 import net.shibboleth.spring.security.CredentialHolder;
 
 /**
@@ -98,6 +99,9 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
     
     /** State token management. */
     @Nullable private StateTokenManager stateTokenManager;
+
+    /** State management. */
+    @Nullable private StateManager stateManager;
     
     /** Transcoding registry. */
     @Nullable private ReloadableService<AttributeTranscoderRegistry> transcodingRegistry;
@@ -397,12 +401,40 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
      * Set the {@link StateTokenManager} to use.
      * 
      * @param manager state token manager
+     * 
+     * @deprecated
      */
+    @Deprecated
     public void setStateTokenManager(@Nonnull final StateTokenManager manager) {
         checkSetterPreconditions();
         
         stateTokenManager = Constraint.isNotNull(manager, "StateTokenManager cannot be null");
     }
+    
+    /** {@inheritDoc} */
+    @Nonnull public StateManager getStateManager() {
+        checkComponentActive();
+        if (stateManager != null) {
+            return stateManager;
+        }
+        
+        if (parent != null && allowInheritance) {
+            return parent.getStateManager();
+        }
+        
+        throw new ConstraintViolationException("StateManager cannot be null");
+    }
+    
+    /**
+     * Set the {@link StateManager} to use.
+     * 
+     * @param manager state manager
+     */
+    public void setStateManager(@Nonnull final StateManager manager) {
+        checkSetterPreconditions();
+        
+        stateManager = Constraint.isNotNull(manager, "StateManager cannot be null");
+    }
 
     /** {@inheritDoc} */
     @Nonnull public ReloadableService<AttributeTranscoderRegistry> getAttributeTranscoderRegistry() {
@@ -614,6 +646,8 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
         
         if (stateTokenManager == null) {
             throw new ComponentInitializationException("StateTokenManager cannot be null");
+        } else if (stateManager == null) {
+            throw new ComponentInitializationException("StateManager cannot be null");
         } else if (transcodingRegistry == null) {
             throw new ComponentInitializationException("AttributeTranscoderRegistry cannot be null");
         } else if (attributeResolver == null) {

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


More information about the commits mailing list