[java-plugin-shibd] branch main updated: Add API and flow support for logout initiators.
Codeberg
noreply at shibboleth.net
Tue Apr 7 15:17:55 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/c67a97a704c3cb6e3c90196860c84ca5d610c6e3
The following commit(s) were added to refs/heads/main by this push:
new c67a97a Add API and flow support for logout initiators.
c67a97a is described below
commit c67a97a704c3cb6e3c90196860c84ca5d610c6e3
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Tue Apr 7 11:17:45 2026 -0400
Add API and flow support for logout initiators.
---
.../sp/logout-initiator/logout-initiator-beans.xml | 19 ++++
.../sp/logout-initiator/logout-initiator-flow.xml | 43 ++++++++
.../flows/sp/logout/initiator/initiator-beans.xml | 21 ++++
.../flows/sp/logout/initiator/initiator-flow.xml | 42 ++++++++
.../sp/flows/LogoutInitiatorFlowTest.java | 112 +++++++++++++++++++++
.../main/java/net/shibboleth/sp/Application.java | 9 ++
.../shibboleth/sp/BasicProtocolSupportService.java | 32 ++++--
.../net/shibboleth/sp/ProtocolSupportService.java | 10 ++
.../net/shibboleth/sp/impl/BasicApplication.java | 59 +++++++++++
.../sp/profile/impl/MapResourceToStateToken.java | 30 +++++-
10 files changed, 368 insertions(+), 9 deletions(-)
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-beans.xml
new file mode 100644
index 0000000..f197e34
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-beans.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+ default-init-method="initialize" default-destroy-method="destroy">
+
+ <bean id="shibboleth.sp.profileId" class="java.lang.String" c:_0="http://shibboleth.net/ns/profiles/sp/session-initiator" />
+ <bean id="shibboleth.sp.loggingId" class="java.lang.String" c:_0="%{sp.service.logging.initiator:SPAgent.SessionInitiator}" />
+
+ <bean id="MapResourceToStateToken"
+ class="net.shibboleth.sp.profile.impl.MapResourceToStateToken" scope="prototype"
+ p:createOutputObjects="true"
+ p:targetRequired="false"
+ p:errorFatal="%{sp.stateToken.errorsFatal:false}" />
+
+</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-flow.xml
new file mode 100644
index 0000000..b9da789
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-flow.xml
@@ -0,0 +1,43 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+ parent="sp/application">
+
+ <action-state id="InitializeProfileRequestContext">
+ <evaluate expression="InitializeProfileRequestContext" />
+ <evaluate expression="'proceed'" />
+
+ <!-- Branch to parent flow for authentication. -->
+ <transition on="proceed" to="AuthenticationSetup" />
+ </action-state>
+
+ <!-- Resume flow operation after set up by parent. -->
+ <action-state id="DoApplicationOperation">
+ <on-entry>
+ <evaluate expression="new net.shibboleth.shared.collection.ReflectionSafeIterator(opensamlProfileRequestContext.ensureSubcontext(T(net.shibboleth.sp.context.AgentRequestContext)).getApplication().getLogoutInitiators(opensamlProfileRequestContext).iterator())" result="flowScope.LogoutInitiatorIterator" />
+ </on-entry>
+ <evaluate expression="MapResourceToStateToken" />
+ <evaluate expression="'proceed'" />
+
+ <!-- Branch to child flow for actual work. -->
+ <transition on="proceed" to="CheckIterator" />
+ </action-state>
+
+ <decision-state id="CheckIterator">
+ <if test="LogoutInitiatorIterator.hasNext()" then="CallInitiatorFlow" else="NoPotentialFlow" />
+ </decision-state>
+
+ <subflow-state id="CallInitiatorFlow" subflow="sp/logout/initiator/#{LogoutInitiatorIterator.next()}">
+ <input name="calledAsSubflow" value="true" />
+ <transition on="proceed" to="EncodeAgentResponse" />
+ <transition on="ReselectFlow" to="CheckIterator" />
+ </subflow-state>
+
+ <action-state id="NoPotentialFlow">
+ <evaluate expression="'NoPotentialFlow'" />
+ </action-state>
+
+ <!-- The file really exists in this directory, but it's referenced from extending flow-directories -->
+ <bean-import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/logout-initiator/logout-initiator-beans.xml" />
+
+</flow>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-beans.xml
new file mode 100644
index 0000000..85815b8
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-beans.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+ default-init-method="initialize" default-destroy-method="destroy">
+
+ <bean id="shibboleth.sp.profileId" class="java.lang.String" c:_0="http://shibboleth.net/ns/profiles/sp/session-initiator" />
+ <bean id="shibboleth.sp.loggingId" class="java.lang.String" c:_0="%{sp.service.logging.initiator:SPAgent.SessionInitiator}" />
+
+ <bean id="PreservePostData"
+ class="net.shibboleth.sp.profile.impl.PreservePostData" scope="prototype"
+ p:errorFatal="%{sp.postData.errorsFatal:false}"
+ p:lifetime="%{sp.postData.lifetime:PT15M}"
+ p:storageService-ref="#{'%{sp.postData.StorageService:shibboleth.StorageService}'.trim()}"
+ p:cookieManager-ref="shibboleth.sp.RemotedCookieManager"
+ p:cookiePrefix="#{'%{sp.postData.cookiePrefix:__Host-shibsp_post_}'.trim()}" />
+
+</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-flow.xml
new file mode 100644
index 0000000..93b3882
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-flow.xml
@@ -0,0 +1,42 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+ abstract="true">
+
+ <!-- Rudimentary impediment to direct execution of subflow. -->
+ <input name="calledAsSubflow" type="boolean" required="true" />
+
+ <!-- Defines the possible end-state events, and a global transition rule. -->
+
+ <!-- Successful completion of subflow. -->
+ <end-state id="proceed" />
+
+ <!-- Error events to reflect back from this subflow. -->
+ <end-state id="InvalidEvent" />
+ <end-state id="InvalidProfileContext" />
+ <end-state id="InvalidRelyingPartyContext" />
+ <end-state id="InvalidRelyingPartyConfiguration" />
+ <end-state id="ReselectFlow" />
+ <end-state id="RuntimeException" />
+
+ <action-state id="LogRuntimeException">
+ <on-entry>
+ <evaluate expression="LogRuntimeException.log('net.shibboleth.sp.profile.logoug.initiator', flowExecutionException)" />
+ </on-entry>
+ <evaluate expression="'RuntimeException'" />
+
+ <transition to="RuntimeException" />
+ </action-state>
+
+ <global-transitions>
+ <transition on-exception="java.lang.RuntimeException" to="LogRuntimeException" />
+ <transition on="InvalidProfileContext" to="InvalidProfileContext" />
+ <transition on="InvalidRelyingPartyContext" to="InvalidRelyingPartyContext" />
+ <transition on="InvalidRelyingPartyConfiguration" to="InvalidRelyingPartyConfiguration" />
+ <transition on="ReselectFlow" to="ReselectFlow" />
+ <transition on="RuntimeException" to="RuntimeException" />
+ </global-transitions>
+
+ <bean-import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/logout/initiator/initiator-beans.xml" />
+
+</flow>
diff --git a/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/LogoutInitiatorFlowTest.java b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/LogoutInitiatorFlowTest.java
new file mode 100644
index 0000000..dd78132
--- /dev/null
+++ b/sp-conf-impl/src/test/java/net/shibboleth/sp/flows/LogoutInitiatorFlowTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.flows;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.profile.action.EventIds;
+import org.springframework.webflow.executor.FlowExecutionResult;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.sp.ddf.DDF;
+import net.shibboleth.sp.profile.SPConstants;
+
+/**
+ * Unit test for the SP logout-initiator flow (basics only).
+ */
+public class LogoutInitiatorFlowTest extends AbstractSPFlowTest {
+
+ /** Flow ID. */
+ @Nonnull public static final String FLOW_ID = "sp/logout-initiator";
+
+ protected LogoutInitiatorFlowTest() {
+ super(FLOW_ID);
+ }
+
+ /**
+ * Test flow with no application specified.
+ * @throws IOException
+ */
+ @Test
+ public void testNoApplication() throws IOException {
+ setDefaultAuth();
+ setRequest("POST", new DDF(null));
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+ }
+
+ /**
+ * Test flow with invalid application ID.
+ * @throws IOException
+ */
+ @Test
+ public void testBadApplication() throws IOException {
+ setDefaultAuth();
+
+ final DDF input = new DDF(null).structure();
+ input.addmember(SPConstants.APPLICATION).string("foo");
+ setRequest("POST", input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, EventIds.INVALID_MESSAGE);
+ }
+
+ /**
+ * Test flow with no initiator subflows installed.
+ * @throws IOException
+ */
+ @Test
+ public void testNoFlows() throws IOException {
+ setDefaultAuth();
+
+ final DDF input = new DDF(null).structure();
+ input.addmember(SPConstants.APPLICATION).string(APPLICATION_ID);
+ input.addmember(SPConstants.TARGET).unsafe_string("https://sp.example.org".getBytes(StandardCharsets.UTF_8));
+ setRequest("POST", input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
+ }
+
+
+ /**
+ * Test flow with no initiator subflows installed.
+ * @throws IOException
+ */
+ @Test
+ public void testNoFlowsNoTarget() throws IOException {
+ setDefaultAuth();
+
+ final DDF input = new DDF(null).structure();
+ input.addmember(SPConstants.APPLICATION).string(APPLICATION_ID);
+ setRequest("POST", input);
+
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertFlowExecutionResult(result, FLOW_ID);
+ assertFlowExecutionOutcome(result.getOutcome());
+ assertOutputMessageEvent(result, AuthnEventIds.NO_POTENTIAL_FLOW);
+ }
+
+}
\ No newline at end of file
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 4cdfd61..bbe3915 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
@@ -93,6 +93,15 @@ public interface Application extends RelyingPartyConfigurationResolver {
*/
@Nonnull List<String> getTokenConsumers(@Nullable final ProfileRequestContext profileRequestContext);
+ /**
+ * Gets an ordered list of logout initiator flows to attempt for this application.
+ *
+ * @param profileRequestContext profile request context
+ *
+ * @return ordered list of unprefixed flow IDs
+ */
+ @Nonnull List<String> getLogoutInitiators(@Nullable final ProfileRequestContext profileRequestContext);
+
/**
* Gets the {@link StateTokenManager} to use for thie application.
*
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/BasicProtocolSupportService.java b/sp-server-api/src/main/java/net/shibboleth/sp/BasicProtocolSupportService.java
index 29e7e98..6757095 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/BasicProtocolSupportService.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/BasicProtocolSupportService.java
@@ -39,11 +39,14 @@ public class BasicProtocolSupportService extends AbstractIdentifiableInitializab
/** Spring auto-wiring order. */
private int order;
- /** Initiator flow IDs. */
- @Nonnull private List<String> initiators;
+ /** Session Initiator flow IDs. */
+ @Nonnull private List<String> sessionInitiators;
/** Consumer flow IDs. */
@Nonnull private List<String> consumers;
+
+ /** Logout Initiator flow IDs. */
+ @Nonnull private List<String> logoutInitiators;
/** Non-metadata-driven verified configurations. */
@Nonnull private Collection<ProfileConfiguration> profileConfigurations;
@@ -59,8 +62,9 @@ public class BasicProtocolSupportService extends AbstractIdentifiableInitializab
/** Constructor. */
public BasicProtocolSupportService() {
- initiators = CollectionSupport.emptyList();
+ sessionInitiators = CollectionSupport.emptyList();
consumers = CollectionSupport.emptyList();
+ logoutInitiators = CollectionSupport.emptyList();
profileConfigurations = CollectionSupport.emptySet();
metadataDrivenProfileConfigurations = CollectionSupport.emptySet();
unverifiedProfileConfigurations = CollectionSupport.emptySet();
@@ -85,18 +89,18 @@ public class BasicProtocolSupportService extends AbstractIdentifiableInitializab
/** {@inheritDoc} */
@Nonnull @Unmodifiable @NotLive public List<String> getSessionInitiators() {
- return initiators;
+ return sessionInitiators;
}
/**
- * Sets the ordered list of initiator flow IDs to install.
+ * Sets the ordered list of session initiator flow IDs to install.
*
* @param flows ordered list of unprefixed initiator flow IDs
*/
public void setSessionInitiators(@Nullable final List<String> flows) {
checkSetterPreconditions();
- initiators = CollectionSupport.copyToList(StringSupport.normalizeStringCollection(flows));
+ sessionInitiators = CollectionSupport.copyToList(StringSupport.normalizeStringCollection(flows));
}
/** {@inheritDoc} */
@@ -115,6 +119,22 @@ public class BasicProtocolSupportService extends AbstractIdentifiableInitializab
consumers = CollectionSupport.copyToList(StringSupport.normalizeStringCollection(flows));
}
+ /** {@inheritDoc} */
+ @Nonnull @Unmodifiable @NotLive public List<String> getLogoutInitiators() {
+ return logoutInitiators;
+ }
+
+ /**
+ * Sets the ordered list of logout initiator flow IDs to install.
+ *
+ * @param flows ordered list of unprefixed initiator flow IDs
+ */
+ public void setLogoutInitiators(@Nullable final List<String> flows) {
+ checkSetterPreconditions();
+
+ logoutInitiators = CollectionSupport.copyToList(StringSupport.normalizeStringCollection(flows));
+ }
+
/** {@inheritDoc} */
@Nonnull @Unmodifiable @NotLive public Collection<ProfileConfiguration> getDefaultProfileConfigurations(
boolean metadataDriven) {
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/ProtocolSupportService.java b/sp-server-api/src/main/java/net/shibboleth/sp/ProtocolSupportService.java
index e91497c..4e08daa 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/ProtocolSupportService.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/ProtocolSupportService.java
@@ -56,6 +56,16 @@ public interface ProtocolSupportService extends IdentifiedComponent, Initializab
*/
@Nonnull @Unmodifiable @NotLive List<String> getTokenConsumers();
+ /**
+ * Gets a default-ordered list of logout initiator flows supported by this protocol plugin.
+ *
+ * <p>The default order should reflect what "most" deployers would expect to use when adding
+ * support for this plugin to their system.</p>
+ *
+ * @return ordered list of unprefixed flow IDs
+ */
+ @Nonnull @Unmodifiable @NotLive List<String> getLogoutInitiators();
+
/**
* Gets the collection of default {@link ProfileConfiguration} objects supplied by this protocol plugin.
*
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 cb9b753..bb9c0d4 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
@@ -93,6 +93,9 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
/** Token consumer list lookup strategy. */
@NonnullAfterInit private Function<ProfileRequestContext,List<String>> tokenConsumerLookupStrategy;
+ /** Logout initiator list lookup strategy. */
+ @NonnullAfterInit private Function<ProfileRequestContext,List<String>> logoutInitiatorLookupStrategy;
+
/** State token management. */
@Nullable private StateTokenManager stateTokenManager;
@@ -332,6 +335,50 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
tokenConsumerLookupStrategy = Constraint.isNotNull(strategy, "Token consumers lookup strategy cannot be null");
}
+ /** {@inheritDoc} */
+ @Nonnull public List<String> getLogoutInitiators(@Nullable final ProfileRequestContext profileRequestContext) {
+ final List<String> ret = logoutInitiatorLookupStrategy.apply(profileRequestContext);
+ if (ret != null && !ret.isEmpty()) {
+ return ret;
+ }
+
+ if (parent != null && allowInheritance) {
+ return parent.getLogoutInitiators(profileRequestContext);
+ }
+
+ return CollectionSupport.emptyList();
+ }
+
+ /**
+ * Sets the ordered collection of unprefixed logout initiator flow IDs to use for this application.
+ *
+ * @param initiators ordered collection of unprefixed logout initiator flow IDs
+ */
+ public void setLogoutInitiators(@Nullable final Collection<String> initiators) {
+ checkSetterPreconditions();
+
+ if (initiators != null) {
+ logoutInitiatorLookupStrategy = FunctionSupport.constant(
+ CollectionSupport.copyToList(StringSupport.normalizeStringCollection(initiators)));
+ } else {
+ logoutInitiatorLookupStrategy = FunctionSupport.constant(CollectionSupport.emptyList());
+ }
+ }
+
+ /**
+ * Sets the lookup strategy for the ordered collection of unprefixed logout initiator flow IDs
+ * to use for this application.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setLogoutInitiatorsLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,List<String>> strategy) {
+ checkSetterPreconditions();
+
+ logoutInitiatorLookupStrategy = Constraint.isNotNull(strategy,
+ "Logout initiators lookup strategy cannot be null");
+ }
+
/** {@inheritDoc} */
@Nonnull public StateTokenManager getStateTokenManager() {
checkComponentActive();
@@ -559,6 +606,9 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
if (tokenConsumerLookupStrategy == null) {
tokenConsumerLookupStrategy = FunctionSupport.constant(CollectionSupport.emptyList());
}
+ if (logoutInitiatorLookupStrategy == null) {
+ logoutInitiatorLookupStrategy = FunctionSupport.constant(CollectionSupport.emptyList());
+ }
return;
}
@@ -591,6 +641,15 @@ public class BasicApplication extends BasicRelyingPartyConfiguration implements
}
tokenConsumerLookupStrategy = FunctionSupport.constant(CollectionSupport.copyToList(consumers));
}
+
+ if (logoutInitiatorLookupStrategy == null) {
+ final ArrayList<String> initiators = new ArrayList<>();
+ for (final ProtocolSupportService service : protocolServiceManager.getComponents()) {
+ assert service != null;
+ initiators.addAll(StringSupport.normalizeStringCollection(service.getLogoutInitiators()));
+ }
+ logoutInitiatorLookupStrategy = FunctionSupport.constant(CollectionSupport.copyToList(initiators));
+ }
}
/** {@inheritDoc} */
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/MapResourceToStateToken.java b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/MapResourceToStateToken.java
index f8ef3a4..d09afca 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/MapResourceToStateToken.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/profile/impl/MapResourceToStateToken.java
@@ -36,7 +36,7 @@ import net.shibboleth.sp.profile.SPConstants;
*
* <p>The existence of a {@link SPConstants#STATE} member will cause the action
* to be skipped, while the absence of {@link SPConstants#TARGET} will result in
- * failure.</p>
+ * conditional failure.</p>
*
* <p>Errors may be ignored or result in an {@link EventIds#IO_ERROR} event.</p>
*
@@ -52,12 +52,20 @@ public class MapResourceToStateToken extends AbstractApplicationAction {
/** Whether an error constructing a state token is fatal. */
private boolean errorFatal;
+ /** Whether to require target parameter in the absence of a state token. */
+ private boolean targetRequired;
+
/** Agent input. */
@NonnullBeforeExec private DDF input;
/** Target resource to operate on. */
@NonnullBeforeExec private byte[] target;
+ /** Constructor. */
+ public MapResourceToStateToken() {
+ targetRequired = true;
+ }
+
/**
* Sets whether an error computing a state token should result in a fatal event.
*
@@ -70,6 +78,20 @@ public class MapResourceToStateToken extends AbstractApplicationAction {
errorFatal = flag;
}
+
+ /**
+ * Sets whether the {@link SPConstants#TARGET} parameter is required if no state token
+ * exists already.
+ *
+ * <p>Defaults to true.</p>
+ *
+ * @param flag flag to set
+ */
+ public void setTargetRequired(final boolean flag) {
+ checkSetterPreconditions();
+
+ targetRequired = flag;
+ }
/** {@inheritDoc} */
@Override
@@ -91,8 +113,10 @@ public class MapResourceToStateToken extends AbstractApplicationAction {
target = input.getmember(SPConstants.TARGET).unsafe_string();
if (target == null) {
- log.warn("{} Input message did not contain {} member", getLogPrefix(), SPConstants.TARGET);
- ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+ if (targetRequired) {
+ log.warn("{} Input message did not contain {} member", getLogPrefix(), SPConstants.TARGET);
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MESSAGE);
+ }
return false;
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list