[java-plugin-shibd] branch main updated: Add descriptors with activation control for session initiator flows
Codeberg
noreply at shibboleth.net
Tue Aug 4 18:53:28 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/cdbf83987884649471e61217a7ea21a9f5c67508
The following commit(s) were added to refs/heads/main by this push:
new cdbf839 Add descriptors with activation control for session initiator flows
cdbf839 is described below
commit cdbf83987884649471e61217a7ea21a9f5c67508
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Aug 4 14:53:13 2026 -0400
Add descriptors with activation control for session initiator flows
---
.../META-INF/net.shibboleth.idp/postconfig.xml | 23 +++++-
.../session-initiator/session-initiator-beans.xml | 1 -
.../session-initiator/session-initiator-flow.xml | 14 +++-
.../profile/BasicLogoutConsumerFlowDescriptor.java | 2 +
...va => BasicSessionInitiatorFlowDescriptor.java} | 16 ++--
.../profile/BasicTokenConsumerFlowDescriptor.java | 2 +
.../sp/profile/SessionInitiatorFlowDescriptor.java | 47 +++++++++++
.../SessionInitiatorFlowDescriptorManager.java | 93 ++++++++++++++++++++++
8 files changed, 186 insertions(+), 12 deletions(-)
diff --git a/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index ebcf35b..493341d 100644
--- a/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -73,7 +73,11 @@
<bean id="shibboleth.RemotedHttpServletRequestSupplier" class="net.shibboleth.sp.messaging.impl.RemotedHttpServletRequestSupplier" />
<bean id="shibboleth.RemotedHttpServletResponseSupplier" class="net.shibboleth.sp.messaging.impl.RemotedlHttpServletResponseSupplier" />
- <!-- Management bean to collect and expose consumer flow descriptors. -->
+ <!-- Management beans to collect and expose flow descriptors. -->
+
+ <bean id="shibboleth.sp.SessionInitiatorFlowDescriptorManager"
+ class="net.shibboleth.sp.profile.impl.SessionInitiatorFlowDescriptorManager"
+ p:components="#{getObject('shibboleth.sp.AvailableSessionInitiatorFlows')}" />
<bean id="shibboleth.sp.TokenConsumerFlowDescriptorManager"
class="net.shibboleth.sp.profile.impl.TokenConsumerFlowDescriptorManager"
@@ -83,6 +87,23 @@
class="net.shibboleth.sp.profile.impl.LogoutConsumerFlowDescriptorManager"
p:components="#{getObject('shibboleth.sp.AvailableLogoutConsumerFlows')}" />
+ <!-- Flow Descriptor for built-in discovery flow. -->
+
+ <bean id="shibboleth.sp.DiscoveryParameterCondition"
+ class="net.shibboleth.sp.profile.context.logic.InputStartsWithPredicate">
+ <constructor-arg>
+ <util:constant static-field="net.shibboleth.sp.profile.InitiatorConstants.DISCOVERY_RETURN_URL" />
+ </constructor-arg>
+ <constructor-arg>
+ <value>http</value>
+ </constructor-arg>
+ </bean>
+
+ <bean p:id="sp/initiator/disco" class="net.shibboleth.sp.profile.BasicSessionInitiatorFlowDescriptor"
+ p:activationCondition-ref="shibboleth.sp.DiscoveryParameterCondition" />
+
+ <!-- Misc beans. -->
+
<bean id="shibboleth.sp.RemotedCookieManager" class="net.shibboleth.shared.net.CookieManager" lazy-init="true"
p:guardSetAttribute="false"
p:httpServletRequestSupplier-ref="shibboleth.RemotedHttpServletRequestSupplier"
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-beans.xml
index 47ae7b8..fbad258 100644
--- a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-beans.xml
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-beans.xml
@@ -14,5 +14,4 @@
<bean id="RecoverStateData"
class="net.shibboleth.sp.profile.impl.RecoverStateData" scope="prototype" />
-
</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-flow.xml
index 6e52b2c..f6c7716 100644
--- a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-flow.xml
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/session-initiator/session-initiator-flow.xml
@@ -25,17 +25,25 @@
</action-state>
<decision-state id="CheckIterator">
- <if test="SessionInitiatorIterator.hasNext()" then="CallInitiatorFlow" else="CheckForDiscovery" />
+ <if test="SessionInitiatorIterator.hasNext()" then="CheckFlowActivation" else="CheckForDiscovery" />
</decision-state>
- <subflow-state id="CallInitiatorFlow" subflow="sp/initiator/#{SessionInitiatorIterator.next()}">
+ <decision-state id="CheckFlowActivation">
+ <on-entry>
+ <evaluate expression="SessionInitiatorIterator.next()" result="flowScope.SessionInitiatorFlow" />
+ </on-entry>
+ <if test="flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.sp.SessionInitiatorFlowDescriptorManager').isActive('sp/initiator/' + SessionInitiatorFlow, opensamlProfileRequestContext)"
+ then="CallInitiatorFlow" else="CheckIterator" />
+ </decision-state>
+
+ <subflow-state id="CallInitiatorFlow" subflow="sp/initiator/#{SessionInitiatorFlow}">
<input name="calledAsSubflow" value="true" />
<transition on="proceed" to="EncodeAgentResponse" />
<transition on="ReselectFlow" to="CheckIterator" />
</subflow-state>
<decision-state id="CheckForDiscovery">
- <if test="opensamlProfileRequestContext.ensureSubcontext(T(net.shibboleth.sp.context.AgentRequestContext)).getApplication().getDiscoveryService(opensamlProfileRequestContext) != null"
+ <if test="opensamlProfileRequestContext.ensureSubcontext(T(net.shibboleth.sp.context.AgentRequestContext)).getApplication().getDiscoveryService(opensamlProfileRequestContext) != null and flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.sp.SessionInitiatorFlowDescriptorManager').isActive('sp/initiator/disco', opensamlProfileRequestContext)"
then="CallDiscoveryFlow"
else="NoPotentialFlow" />
</decision-state>
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicLogoutConsumerFlowDescriptor.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicLogoutConsumerFlowDescriptor.java
index 6344582..0a6b39d 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicLogoutConsumerFlowDescriptor.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicLogoutConsumerFlowDescriptor.java
@@ -48,6 +48,8 @@ public class BasicLogoutConsumerFlowDescriptor extends AbstractIdentifiableIniti
/**
* Set activation condition to determine whether this flow supports a request.
*
+ * <p>Defaults to false.</p>
+ *
* @param condition condition to use
*/
public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicSessionInitiatorFlowDescriptor.java
similarity index 80%
copy from sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java
copy to sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicSessionInitiatorFlowDescriptor.java
index a84fc1d..3cabd69 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicSessionInitiatorFlowDescriptor.java
@@ -27,17 +27,17 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.logic.PredicateSupport;
/**
- * Basic implementation of a descriptor for a token consumer flow.
+ * Basic implementation of a descriptor for a session initiator flow.
*/
-public class BasicTokenConsumerFlowDescriptor extends AbstractIdentifiableInitializableComponent
- implements TokenConsumerFlowDescriptor {
+public class BasicSessionInitiatorFlowDescriptor extends AbstractIdentifiableInitializableComponent
+ implements SessionInitiatorFlowDescriptor {
/** Whether this flow supports a particular request. */
@Nonnull private Predicate<ProfileRequestContext> activationCondition;
/** Constructor. */
- public BasicTokenConsumerFlowDescriptor() {
- activationCondition = PredicateSupport.alwaysFalse();
+ public BasicSessionInitiatorFlowDescriptor() {
+ activationCondition = PredicateSupport.alwaysTrue();
}
/** {@inheritDoc} */
@@ -48,6 +48,8 @@ public class BasicTokenConsumerFlowDescriptor extends AbstractIdentifiableInitia
/**
* Set activation condition to determine whether this flow supports a request.
*
+ * <p>Defaults to true.</p>
+ *
* @param condition condition to use
*/
public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
@@ -69,8 +71,8 @@ public class BasicTokenConsumerFlowDescriptor extends AbstractIdentifiableInitia
return true;
}
- if (obj instanceof BasicTokenConsumerFlowDescriptor) {
- return ensureId().equals(((BasicTokenConsumerFlowDescriptor) obj).getId());
+ if (obj instanceof BasicSessionInitiatorFlowDescriptor) {
+ return ensureId().equals(((BasicSessionInitiatorFlowDescriptor) obj).getId());
}
return false;
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java
index a84fc1d..f858c14 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/BasicTokenConsumerFlowDescriptor.java
@@ -48,6 +48,8 @@ public class BasicTokenConsumerFlowDescriptor extends AbstractIdentifiableInitia
/**
* Set activation condition to determine whether this flow supports a request.
*
+ * <p>Defaults to false.</p>
+ *
* @param condition condition to use
*/
public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/profile/SessionInitiatorFlowDescriptor.java b/sp-server-api/src/main/java/net/shibboleth/sp/profile/SessionInitiatorFlowDescriptor.java
new file mode 100644
index 0000000..4eb563e
--- /dev/null
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/profile/SessionInitiatorFlowDescriptor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.profile;
+
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.idp.profile.FlowDescriptor;
+
+/**
+ * A descriptor for a session initiator subflow.
+ *
+ * <p>Session initiators are the portion of the SP responsible for initiating SSO protocol requests.
+ * They exist in every SSO protocol in some sense but are usually not formalized, though most protocols
+ * have extensions nobody bothers to implement to represent the idea of an endpoint where a request can
+ * get kicked off.</p>
+ *
+ * <p>The primary need for this is to associate each subflow with a condition that can
+ * determine whether a given request is handled by a given subflow. Sometimes this may be
+ * a no-op without more information that is only known once the flow runs, but some flows
+ * can optimize not running in some cases.</p>
+ */
+public interface SessionInitiatorFlowDescriptor extends FlowDescriptor {
+
+ /**
+ * Gets the activation condition to run to determine whether this flow can handle the request.
+ *
+ * @return a condition governing use of this flow
+ */
+ @Nonnull Predicate<ProfileRequestContext> getActivationCondition();
+
+}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/SessionInitiatorFlowDescriptorManager.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/SessionInitiatorFlowDescriptorManager.java
new file mode 100644
index 0000000..89ba78d
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/SessionInitiatorFlowDescriptorManager.java
@@ -0,0 +1,93 @@
+/*
+ * 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.profile.impl;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.spring.config.IdentifiedComponentManager;
+import net.shibboleth.sp.profile.SessionInitiatorFlowDescriptor;
+
+/**
+ * Manager of {@link SessionInitiatorFlowDescriptor} objects.
+ */
+public class SessionInitiatorFlowDescriptorManager extends IdentifiedComponentManager<SessionInitiatorFlowDescriptor> {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(SessionInitiatorFlowDescriptorManager.class);
+
+ /** Map of flow descriptors. */
+ @Nonnull private Map<String,SessionInitiatorFlowDescriptor> sessionInitiatorMap;
+
+ /**
+ * Constructor.
+ *
+ * @param freeObjects free-standing objects
+ */
+ @Autowired
+ public SessionInitiatorFlowDescriptorManager(@Nullable final Collection<SessionInitiatorFlowDescriptor> freeObjects) {
+ super(freeObjects);
+
+ sessionInitiatorMap = CollectionSupport.emptyMap();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ sessionInitiatorMap = getComponents().stream()
+ .collect(CollectionSupport.nonnullCollector(
+ Collectors.toUnmodifiableMap(SessionInitiatorFlowDescriptor::getId, fd -> fd))).get();
+ }
+
+ /**
+ * Checks if a flow ID corresponds to a valid flow that in turn ius active for the request.
+ *
+ * @param id flow ID
+ * @param profileRequestContext current profile request context
+ *
+ * @return true iff the flow exists and is active (should run)
+ */
+ public boolean isActive(@Nonnull @NotEmpty final String id,
+ @Nullable final ProfileRequestContext profileRequestContext) {
+ final SessionInitiatorFlowDescriptor flow = sessionInitiatorMap.get(id);
+ if (flow != null) {
+ final boolean active = flow.getActivationCondition().test(profileRequestContext);
+ if (active) {
+ log.debug("Session initiator flow ({}) active, attempting", id);
+ } else {
+ log.info("Session initiator flow ({}) not active, skipping", id);
+ }
+ return active;
+ } else {
+ log.warn("Session initiator flow ({}) not registered", id);
+ return false;
+ }
+ }
+
+}
\ 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