[java-identity-provider] branch main updated: IDP-2319- Login fows should support a dedicated c14n list
Scott Cantor
cantor.2 at osu.edu
Fri Feb 21 20:43:27 UTC 2025
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=175afe25ac8bf234e1a22c0d22599ed8975a479f
The following commit(s) were added to refs/heads/main by this push:
new 175afe25a IDP-2319- Login fows should support a dedicated c14n list
175afe25a is described below
commit 175afe25ac8bf234e1a22c0d22599ed8975a479f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Feb 21 15:43:24 2025 -0500
IDP-2319- Login fows should support a dedicated c14n list
https://shibboleth.atlassian.net/browse/IDP-2319
Auto-wire post login flows.
Differentiate flow ID from descriptor bean ID.
Add per-login flow property hook to control list of beans to run.
---
...LoginSubjectCanonicalizationFlowDescriptor.java | 29 ++++++++
.../SubjectCanonicalizationFlowDescriptor.java | 70 ++++++++++++++++---
.../context/SubjectCanonicalizationContext.java | 4 +-
.../PopulateSubjectCanonicalizationContext.java | 81 +++++++++++++++++++---
...bjectCanonicalizationFlowDescriptorManager.java | 45 ++++++++++++
.../impl/SelectSubjectCanonicalizationFlow.java | 32 +++++----
.../shibboleth/idp/conf/subject-c14n-system.xml | 8 ++-
.../idp/flows/authn/external-authn-beans.xml | 5 +-
.../idp/flows/authn/function-authn-beans.xml | 5 +-
.../idp/flows/authn/ipaddress-authn-beans.xml | 5 +-
.../shibboleth/idp/flows/authn/mfa-authn-beans.xml | 6 +-
.../idp/flows/authn/password-authn-beans.xml | 6 +-
.../idp/flows/authn/remoteuser-authn-beans.xml | 5 +-
.../authn/remoteuser-internal-authn-beans.xml | 5 +-
.../idp/flows/authn/saml-authn-beans.xml | 5 +-
.../idp/flows/authn/spnego-authn-beans.xml | 5 +-
.../idp/flows/authn/x509-authn-beans.xml | 5 +-
.../idp/flows/authn/x509-internal-authn-beans.xml | 5 +-
.../idp/module/conf/authn/authn.properties | 25 ++++++-
19 files changed, 303 insertions(+), 48 deletions(-)
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PostLoginSubjectCanonicalizationFlowDescriptor.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PostLoginSubjectCanonicalizationFlowDescriptor.java
new file mode 100644
index 000000000..7c3ff35d2
--- /dev/null
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/PostLoginSubjectCanonicalizationFlowDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ * 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.idp.authn;
+
+import javax.security.auth.Subject;
+
+/**
+ * Marker subtype for a {@link SubjectCanonicalizationFlowDescriptor} that applies to the post-login
+ * scenario of transforming the {@link Subject} produced for an {@link AuthenticationResult} into
+ * a final name.
+ *
+ * @since 5.2.0
+ */
+public class PostLoginSubjectCanonicalizationFlowDescriptor extends SubjectCanonicalizationFlowDescriptor {
+
+
+}
\ No newline at end of file
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/SubjectCanonicalizationFlowDescriptor.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/SubjectCanonicalizationFlowDescriptor.java
index 767df892d..0478fe962 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/SubjectCanonicalizationFlowDescriptor.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/SubjectCanonicalizationFlowDescriptor.java
@@ -17,15 +17,20 @@ package net.shibboleth.idp.authn;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
import com.google.common.base.MoreObjects;
+import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
import net.shibboleth.idp.profile.FlowDescriptor;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.StringSupport;
/**
* A descriptor for a subject canonicalization flow.
@@ -33,14 +38,16 @@ import net.shibboleth.shared.logic.PredicateSupport;
* <p>
* A flow models a sequence of profile actions that performs canonicalization of a {@link javax.security.auth.Subject}
* into a string-form principal name. Flows can do essentially anything, including interact with the subject, but must
- * include an activation predicate to indicate their suitability based on the content of the
- * {@link ProfileRequestContext}, particularly the required
- * {@link net.shibboleth.idp.authn.context.SubjectCanonicalizationContext} child context.
+ * include an activation predicate to indicate their suitability based on the content of the context tree, particularly
+ * the required {@link SubjectCanonicalizationContext} child context.
* </p>
*/
public class SubjectCanonicalizationFlowDescriptor extends AbstractIdentifiableInitializableComponent implements
FlowDescriptor, Predicate<ProfileRequestContext> {
+ /** Optional flow ID that may differ from component ID. */
+ @NonnullAfterInit private String flowId;
+
/** Predicate that must be true for this flow to be usable for a given request. */
@Nonnull private Predicate<ProfileRequestContext> activationCondition;
@@ -48,7 +55,34 @@ public class SubjectCanonicalizationFlowDescriptor extends AbstractIdentifiableI
public SubjectCanonicalizationFlowDescriptor() {
activationCondition = PredicateSupport.alwaysTrue();
}
+
+ /**
+ * Gets the flow ID for this descriptor (inclusive of the c14n/ prefix).
+ *
+ * @return flow ID
+ */
+ @NonnullAfterInit public String getFlowId() {
+ return flowId;
+ }
+ /**
+ * Sets the flow ID for this descriptor.
+ *
+ * <p>This defaults to the component ID, but can be overridden to allow multiple
+ * components to be defined for a given webflow.</p>
+ *
+ * @param id
+ *
+ * @since 5.2.0
+ */
+ public void setFlowId(@Nullable final String id) {
+ checkSetterPreconditions();
+ flowId = StringSupport.trimOrNull(id);
+ if (id != null) {
+ Constraint.isFalse(flowId.startsWith("c14n/"), "Flow ID must begin with c14n/ prefix.");
+ }
+ }
+
/**
* Set the activation condition in the form of a {@link Predicate} such that iff the condition evaluates to true
* should the corresponding flow be allowed/possible.
@@ -59,19 +93,36 @@ public class SubjectCanonicalizationFlowDescriptor extends AbstractIdentifiableI
checkSetterPreconditions();
activationCondition = Constraint.isNotNull(condition, "Activation condition predicate cannot be null");
}
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ // Backfill flow ID with component ID.
+ if (flowId == null) {
+ flowId = ensureId();
+ if (!flowId.startsWith("c14n/")) {
+ throw new ComponentInitializationException("Defaulted flow ID must begin with c14n/ prefix.");
+ }
+ }
+ }
/** {@inheritDoc} */
- @Override public boolean test(final ProfileRequestContext input) {
+ public boolean test(final ProfileRequestContext input) {
+ checkComponentActive();
return activationCondition.test(input);
}
/** {@inheritDoc} */
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return getId().hashCode();
}
/** {@inheritDoc} */
- @Override public boolean equals(final Object obj) {
+ @Override
+ public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@@ -80,15 +131,16 @@ public class SubjectCanonicalizationFlowDescriptor extends AbstractIdentifiableI
return true;
}
- if (obj instanceof SubjectCanonicalizationFlowDescriptor) {
- return getId().equals(((SubjectCanonicalizationFlowDescriptor) obj).getId());
+ if (obj instanceof SubjectCanonicalizationFlowDescriptor scfd) {
+ return getId().equals(scfd.getId());
}
return false;
}
/** {@inheritDoc} */
- @Override public String toString() {
+ @Override
+ public String toString() {
return MoreObjects.toStringHelper(this).add("flowId", getId()).toString();
}
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/SubjectCanonicalizationContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/SubjectCanonicalizationContext.java
index 6d8671007..6b31e18de 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/SubjectCanonicalizationContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/SubjectCanonicalizationContext.java
@@ -53,10 +53,10 @@ public final class SubjectCanonicalizationContext extends BaseContext {
@Nullable private String responderId;
/** Flows that could potentially be used. */
- @Nonnull private final Map<String, SubjectCanonicalizationFlowDescriptor> potentialFlows;
+ @Nonnull private final Map<String,SubjectCanonicalizationFlowDescriptor> potentialFlows;
/** Previously attempted flows (could be failures or intermediate results). */
- @Nonnull private final Map<String, SubjectCanonicalizationFlowDescriptor> intermediateFlows;
+ @Nonnull private final Map<String,SubjectCanonicalizationFlowDescriptor> intermediateFlows;
/** The last c14 flow attempted. */
@Nullable private SubjectCanonicalizationFlowDescriptor attemptedFlow;
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PopulateSubjectCanonicalizationContext.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PopulateSubjectCanonicalizationContext.java
index ac673e01d..6af7a86ef 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PopulateSubjectCanonicalizationContext.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PopulateSubjectCanonicalizationContext.java
@@ -15,8 +15,12 @@
package net.shibboleth.idp.authn.impl;
import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.profile.context.ProfileRequestContext;
import org.slf4j.Logger;
@@ -27,13 +31,19 @@ import net.shibboleth.idp.authn.context.SubjectCanonicalizationContext;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.spring.config.IdentifiedComponentManager;
/**
* An action that populates a {@link SubjectCanonicalizationContext} with the
- * {@link SubjectCanonicalizationFlowDescriptor} objects configured into the IdP.
+ * {@link SubjectCanonicalizationFlowDescriptor} objects configured into the IdP,
+ * optionally along with the actual descriptor IDs to try in a particular order.
+ *
+ * <p>The latter set filters the former and controls the order of insertion
+ * into the context.</p>
*
* @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
- * @pre <pre>ProfileRequestContext.getSubcontext(SubjectCanonicalizationContext.class, false) != null</pre>
+ * @pre <pre>ProfileRequestContext.getSubcontext(SubjectCanonicalizationContext.class) != null</pre>
* @post The SubjectCanonicalizationContext is modified as above.
*/
public class PopulateSubjectCanonicalizationContext extends AbstractSubjectCanonicalizationAction {
@@ -42,11 +52,15 @@ public class PopulateSubjectCanonicalizationContext extends AbstractSubjectCanon
@Nonnull private final Logger log = LoggerFactory.getLogger(PopulateSubjectCanonicalizationContext.class);
/** The flows to make available for possible use. */
- @Nonnull private Collection<SubjectCanonicalizationFlowDescriptor> availableFlows;
+ @Nonnull private Map<String,SubjectCanonicalizationFlowDescriptor> availableFlows;
+
+ /** This is the actual set of descriptor component IDs to install for use in their designated order. */
+ @Nonnull private Collection<String> usableFlows;
/** Constructor. */
PopulateSubjectCanonicalizationContext() {
- availableFlows = CollectionSupport.emptyList();
+ availableFlows = new LinkedHashMap<>();
+ usableFlows = CollectionSupport.emptyList();
}
/**
@@ -56,18 +70,67 @@ public class PopulateSubjectCanonicalizationContext extends AbstractSubjectCanon
*/
public void setAvailableFlows(@Nonnull final Collection<SubjectCanonicalizationFlowDescriptor> flows) {
checkSetterPreconditions();
- availableFlows = CollectionSupport.copyToList(Constraint.isNotNull(flows, "Flow collection cannot be null"));
+
+ Constraint.isNotNull(flows, "Flow collection cannot be null").forEach(fd -> {
+ availableFlows.put(fd.ensureId(), fd);
+ });
}
+
+ /**
+ * Set the flows available for possible use via a manager object.
+ *
+ * <p>Use of this variant setter should be accompanied by use of the {@link #setUsableFlows(List)} method
+ * introduced to filter the eventual list.</p>
+ *
+ * @param manager the flows available for possible use
+ *
+ * @since 5.2.0
+ */
+ public void setAvailableFlows(
+ @Nonnull final IdentifiedComponentManager<SubjectCanonicalizationFlowDescriptor> manager) {
+ checkSetterPreconditions();
+ manager.getComponents().forEach(fd -> {
+ availableFlows.put(fd.ensureId(), fd);
+ });
+ }
+
+ /**
+ * Set an optional ordered list of flow descriptor IDs that should filter the available flows and
+ * provide an alternative order of use from the injected collection's implied order.
+ *
+ * @param usable {@link SubjectCanonicalizationFlowDescriptor} IDs, in ordered list of use
+ *
+ * @since 5.2.0
+ */
+ public void setUsableFlows(@Nullable final List<String> usable) {
+ checkSetterPreconditions();
+ // This method does guarantee order based on the source.
+ usableFlows = StringSupport.normalizeStringCollection(usable);
+ }
+
/** {@inheritDoc} */
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final SubjectCanonicalizationContext c14nContext) {
- log.debug("{} Installing {} canonicalization flows into SubjectCanonicalizationContext", getLogPrefix(),
- availableFlows.size());
- for (final SubjectCanonicalizationFlowDescriptor desc : availableFlows) {
- c14nContext.getPotentialFlows().put(desc.ensureId(), desc);
+ if (usableFlows.isEmpty()) {
+ log.debug("{} Installing {} c14n flows into SubjectCanonicalizationContext", getLogPrefix(),
+ availableFlows.size());
+ // It is presumed (and we need for this) to maintain order.
+ c14nContext.getPotentialFlows().putAll(availableFlows);
+ } else {
+ for (final String id : usableFlows) {
+ final var fd = availableFlows.get(id);
+ if (fd != null) {
+ c14nContext.getPotentialFlows().put(id, fd);
+ } else {
+ log.warn("{} Skipping installation of flow descriptor '{}', not available in configuration?",
+ getLogPrefix(), id);
+ }
+ }
+ log.debug("{} Installed {} c14n flows into SubjectCanonicalizationContext", getLogPrefix(),
+ c14nContext.getPotentialFlows().size());
}
}
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PostLoginSubjectCanonicalizationFlowDescriptorManager.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PostLoginSubjectCanonicalizationFlowDescriptorManager.java
new file mode 100644
index 000000000..cac472d22
--- /dev/null
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/PostLoginSubjectCanonicalizationFlowDescriptorManager.java
@@ -0,0 +1,45 @@
+/*
+ * 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.idp.authn.impl;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import net.shibboleth.idp.authn.PostLoginSubjectCanonicalizationFlowDescriptor;
+import net.shibboleth.shared.spring.config.IdentifiedComponentManager;
+
+/**
+ * Manager of {@link PostLoginSubjectCanonicalizationFlowDescriptor} objects.
+ *
+ * @since 5.2.0
+ */
+public class PostLoginSubjectCanonicalizationFlowDescriptorManager
+ extends IdentifiedComponentManager<PostLoginSubjectCanonicalizationFlowDescriptor> {
+
+ /**
+ * Constructor.
+ *
+ * @param freeObjects free-standing objects
+ */
+ @Autowired
+ public PostLoginSubjectCanonicalizationFlowDescriptorManager(
+ @Nullable final List<PostLoginSubjectCanonicalizationFlowDescriptor> freeObjects) {
+ super(freeObjects);
+ }
+
+}
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectSubjectCanonicalizationFlow.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectSubjectCanonicalizationFlow.java
index c72a36dad..3183e4922 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectSubjectCanonicalizationFlow.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/SelectSubjectCanonicalizationFlow.java
@@ -41,7 +41,7 @@ import net.shibboleth.shared.primitive.LoggerFactory;
*
* @event {@link AuthnEventIds#NO_POTENTIAL_FLOW}
* @event Selected flow ID to execute
- * @pre <pre>ProfileRequestContext.getSubcontext(SubjectCanonicalizationContext.class, false) != null</pre>
+ * @pre <pre>ProfileRequestContext.getSubcontext(SubjectCanonicalizationContext.class) != null</pre>
*/
public class SelectSubjectCanonicalizationFlow extends AbstractSubjectCanonicalizationAction {
@@ -53,17 +53,20 @@ public class SelectSubjectCanonicalizationFlow extends AbstractSubjectCanonicali
protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final SubjectCanonicalizationContext c14nContext) {
+ if (!super.doPreExecute(profileRequestContext, c14nContext)) {
+ return false;
+ }
+
// Detect a previous attempted flow, and move it to the intermediate collection.
// This will prevent re-selecting the same (probably failed) flow again.
- final SubjectCanonicalizationFlowDescriptor flow = c14nContext.getAttemptedFlow();
+ final SubjectCanonicalizationFlowDescriptor flow = c14nContext.getAttemptedFlow();
if (flow != null) {
- log.info("{} Moving incomplete flow {} to intermediate set, reselecting a different one", getLogPrefix(),
- flow.getId());
- c14nContext.getIntermediateFlows().put(
- flow.ensureId(), c14nContext.getAttemptedFlow());
+ log.info("{} Moving incomplete c14n flow descriptor {} to intermediate set, reselecting different one",
+ getLogPrefix(), flow.getId());
+ c14nContext.getIntermediateFlows().put(flow.ensureId(), c14nContext.getAttemptedFlow());
}
- return super.doPreExecute(profileRequestContext, c14nContext);
+ return true;
}
/** {@inheritDoc} */
@@ -73,12 +76,13 @@ public class SelectSubjectCanonicalizationFlow extends AbstractSubjectCanonicali
final SubjectCanonicalizationFlowDescriptor flow = selectUnattemptedFlow(profileRequestContext, c14nContext);
if (flow == null) {
- log.error("{} No potential flows left to choose from, canonicalization will fail", getLogPrefix());
+ log.error("{} No potential flows left to choose from, c14n will fail", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_POTENTIAL_FLOW);
return;
}
- log.debug("{} Selecting canonicalization flow {}", getLogPrefix(), flow.ensureId());
- ActionSupport.buildEvent(profileRequestContext, flow.ensureId());
+ log.debug("{} Selecting c14n descriptor {} (WebFlow ID: {})", getLogPrefix(), flow.ensureId(),
+ flow.getFlowId());
+ ActionSupport.buildEvent(profileRequestContext, flow.getFlowId());
}
/**
@@ -92,18 +96,18 @@ public class SelectSubjectCanonicalizationFlow extends AbstractSubjectCanonicali
@Nullable private SubjectCanonicalizationFlowDescriptor selectUnattemptedFlow(
@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final SubjectCanonicalizationContext c14nContext) {
+
for (final SubjectCanonicalizationFlowDescriptor flow : c14nContext.getPotentialFlows().values()) {
if (!c14nContext.getIntermediateFlows().containsKey(flow.ensureId())) {
- log.debug("{} Checking canonicalization flow {} for applicability...", getLogPrefix(),
+ log.debug("{} Checking c14n flow descriptor {} for applicability...", getLogPrefix(),
flow.getId());
c14nContext.setAttemptedFlow(flow);
if (flow.test(profileRequestContext)) {
return flow;
}
final Exception ctxException = c14nContext.getException();
- log.debug("{} Canonicalization flow {} was not applicable: {}", getLogPrefix(), flow.getId(),
- ctxException!= null ? ctxException.getMessage()
- : "reason unknown");
+ log.debug("{} C14N flow descriptor {} was not applicable: {}", getLogPrefix(), flow.getId(),
+ ctxException!= null ? ctxException.getMessage() : "reason unknown");
c14nContext.setException(null);
// Note that we don't exclude this flow from possible future selection, since one flow
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/subject-c14n-system.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/subject-c14n-system.xml
index 4a7c06236..d6276c3fb 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/subject-c14n-system.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/subject-c14n-system.xml
@@ -12,6 +12,12 @@
default-init-method="initialize"
default-destroy-method="destroy">
+ <!-- Management bean to collect and expose Post-Login Subject C14N flow descriptors. -->
+
+ <bean id="shibboleth.PostLoginC14NFlowDescriptorManager"
+ class="net.shibboleth.idp.authn.impl.PostLoginSubjectCanonicalizationFlowDescriptorManager"
+ p:components="#{getObject('shibboleth.PostLoginSubjectCanonicalizationFlows')}" />
+
<!-- Dummy beans expected to be redefined by imported resource. -->
<bean id="shibboleth.ProxyNameTransformPredicate" parent="shibboleth.Conditions.FALSE" />
<util:list id="shibboleth.ProxyNameTransformFormats" />
@@ -19,7 +25,7 @@
<import resource="${idp.home}/conf/c14n/subject-c14n.xml" />
<bean id="shibboleth.PostLoginSubjectCanonicalizationFlow" abstract="true"
- class="net.shibboleth.idp.authn.SubjectCanonicalizationFlowDescriptor" />
+ class="net.shibboleth.idp.authn.PostLoginSubjectCanonicalizationFlowDescriptor" />
<bean id="c14n/simple" parent="shibboleth.PostLoginSubjectCanonicalizationFlow">
<property name="activationCondition">
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
index 7b07647a1..66e00d442 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/external-authn-beans.xml
@@ -29,9 +29,12 @@
p:populateAuditContextAction="#{%{idp.authn.External.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.External.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.External.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.External.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
index 51338b0ab..0e4f3efcd 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/function-authn-beans.xml
@@ -28,9 +28,12 @@
p:populateAuditContextAction="#{%{idp.authn.Function.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.Function.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.Function.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.Function.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
index de6966a77..f121bfad7 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/ipaddress-authn-beans.xml
@@ -27,9 +27,12 @@
p:populateAuditContextAction="#{%{idp.authn.IPAddress.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.IPAddress.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.IPAddress.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.IPAddress.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/mfa-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/mfa-authn-beans.xml
index 6f8f7db54..20af79008 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/mfa-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/mfa-authn-beans.xml
@@ -37,7 +37,11 @@
class="net.shibboleth.idp.authn.impl.FinalizeMultiFactorAuthentication.DefaultResultMergingStrategy"
p:useLatestTimestamp="%{idp.authn.MFA.useLatestTimestamp:false}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.MFA.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
+
</beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
index e2a137b9e..eb489d61f 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/password-authn-beans.xml
@@ -69,9 +69,13 @@
p:passwordFieldName="#{getObject('shibboleth.authn.Password.PasswordFieldName') ?: '%{idp.authn.Password.passwordFieldName:j_password}'.trim()}"
p:SSOBypassFieldName="#{getObject('shibboleth.authn.Password.SSOBypassFieldName') ?: '%{idp.authn.Password.ssoBypassFieldName:donotcache}'.trim()}" />
+
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.Password.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<bean id="DefaultCleanupHook" class="net.shibboleth.idp.authn.impl.ValidateCredentials.UsernamePasswordCleanupHook"
p:dataSealer="#{'%{idp.authn.usernameCookieName:}'.trim().isEmpty() ? null : getObject('shibboleth.DataSealer')}"
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
index 807eb9c49..7ea37d60f 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-authn-beans.xml
@@ -29,9 +29,12 @@
p:populateAuditContextAction="#{%{idp.authn.RemoteUser.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.RemoteUser.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.RemoteUser.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.RemoteUser.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
index d07b23ca5..4ae8317f3 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/remoteuser-internal-authn-beans.xml
@@ -59,9 +59,12 @@
p:populateAuditContextAction="#{%{idp.authn.RemoteUserInternal.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.RemoteUserInternal.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.RemoteUserInternal.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.RemoteUserInternal.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/saml-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/saml-authn-beans.xml
index b0dd5da83..8a1a164ee 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/saml-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/saml-authn-beans.xml
@@ -456,8 +456,11 @@
p:attributeExtractionStrategy="#{getObject('shibboleth.authn.SAML.attributeExtractionStrategy')}"
p:loggedAttributeId="%{idp.authn.SAML.loggedAttributeId:}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.SAML.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
</beans>
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
index c6d9e6273..4cafa1ba0 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/spnego-authn-beans.xml
@@ -54,9 +54,12 @@
p:cookieManager-ref="shibboleth.UserPrefsCookieManager"
p:cookieName="%{idp.authn.SPNEGO.cookieName:_idp_spnego_autologin}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.SPNEGO.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
index b901c8917..117bcfcd4 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-authn-beans.xml
@@ -31,9 +31,12 @@
p:populateAuditContextAction="#{%{idp.authn.X509.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('shibboleth.authn.X509.PopulateAuditContext') : null}"
p:writeAuditLogAction="#{%{idp.authn.X509.audit.enabled:%{idp.authn.audit.enabled:false}} ? getObject('WriteAuthnAuditLog') : null}" />
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.X509.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
index 2922e0142..c69c23477 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/x509-internal-authn-beans.xml
@@ -32,9 +32,12 @@
</property>
</bean>
+ <bean id="UsableC14NFlows" parent="shibboleth.CommaDelimStringArray" c:_0="%{idp.authn.X509Internal.c14n.flows:}" />
+
<bean id="PopulateSubjectCanonicalizationContext"
class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
- p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
+ p:availableFlows-ref="shibboleth.PostLoginC14NFlowDescriptorManager"
+ p:usableFlows-ref="UsableC14NFlows" />
<!-- Audit logging beans. -->
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/authn.properties b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/authn.properties
index 143f526da..3d412208c 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/authn.properties
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/authn/authn.properties
@@ -78,6 +78,8 @@
# Default error message handling
#idp.authn.Password.errorMessageFunction = DefaultPasswordErrorFunction
#idp.authn.Password.genericMessageID = authn
+# Optionally specify list of c14n beans to apply
+#idp.authn.Password.c14n.flows =
# Unset if using customized Principals per validator
#idp.authn.Password.addDefaultPrincipals = true
# The Principal collection below is the typical default if not otherwise noted.
@@ -106,6 +108,8 @@
#idp.authn.External.nonBrowserSupported = false
#idp.authn.External.matchExpression =
# Unset if you plan to return full Java Subject from external source
+# Optionally specify list of c14n beans to apply
+#idp.authn.External.c14n.flows =
#idp.authn.External.addDefaultPrincipals = true
# Servlet context-relative path to wherever your implementation lives
idp.authn.External.externalAuthnPath = contextRelative:external.jsp
@@ -115,8 +119,7 @@ idp.authn.External.externalAuthnPath = contextRelative:external.jsp
#idp.authn.RemoteUser.order = 1000
#idp.authn.RemoteUser.nonBrowserSupported = false
#idp.authn.RemoteUser.matchExpression =
-# Unset in most cases only if using the authnMethodHeader or
-# subjectAttribute settings
+# Unset in most cases only if using the authnMethodHeader or subjectAttribute settings
#idp.authn.RemoteUser.addDefaultPrincipals = true
#idp.authn.RemoteUser.checkRemoteUser = true
# Comma-delimited lists of attributes or headers to pull from
@@ -126,6 +129,8 @@ idp.authn.External.externalAuthnPath = contextRelative:external.jsp
#idp.authn.RemoteUser.subjectAttribute =
#idp.authn.RemoteUser.authnMethodHeader =
#idp.authn.RemoteUser.authnAuthorityHeader =
+# Optionally specify list of c14n beans to apply
+#idp.authn.RemoteUser.c14n.flows =
#### RemoteUserInternal ####
@@ -144,6 +149,8 @@ idp.authn.External.externalAuthnPath = contextRelative:external.jsp
#idp.authn.RemoteUserInternal.matchExpression =
#idp.authn.RemoteUserInternal.allowedUsernames =
#idp.authn.RemoteUserInternal.deniedUsernames =
+# Optionally specify list of c14n beans to apply
+#idp.authn.RemoteUserInternal.c14n.flows =
#### SPNEGO ####
@@ -152,6 +159,8 @@ idp.authn.External.externalAuthnPath = contextRelative:external.jsp
#idp.authn.SPNEGO.enforceRun = false
#idp.authn.SPNEGO.refreshKrbConfig = false
#idp.authn.SPNEGO.matchExpression =
+# Optionally specify list of c14n beans to apply
+#idp.authn.SPNEGO.c14n.flows =
idp.authn.SPNEGO.supportedPrincipals = \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos, \
saml1/urn:ietf:rfc:1510
@@ -163,6 +172,8 @@ idp.authn.SPNEGO.supportedPrincipals = \
#idp.authn.X509.saveCertificateToCredentialSet = true
# Servlet context-relative path to wherever your implementation lives
#idp.authn.X509.externalAuthnPath = contextRelative:x509-prompt.jsp
+# Optionally specify list of c14n beans to apply
+#idp.authn.X509.c14n.flows =
idp.authn.X509.supportedPrincipals = \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:X509, \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient, \
@@ -173,6 +184,8 @@ idp.authn.X509.supportedPrincipals = \
#idp.authn.X509Internal.order = 1000
#idp.authn.X509Internal.nonBrowserSupported = false
#idp.authn.X509Internal.saveCertificateToCredentialSet = true
+# Optionally specify list of c14n beans to apply
+#idp.authn.X509Internal.c14n.flows =
idp.authn.X509Internal.supportedPrincipals = \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:X509, \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient, \
@@ -184,6 +197,8 @@ idp.authn.X509Internal.supportedPrincipals = \
#idp.authn.IPAddress.passiveAuthenticationSupported = true
#idp.authn.IPAddress.lifetime = PT60S
#idp.authn.IPAddress.inactivityTimeout = PT60S
+# Optionally specify list of c14n beans to apply
+#idp.authn.IPAddress.c14n.flows =
idp.authn.IPAddress.supportedPrincipals = \
saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol
@@ -191,6 +206,8 @@ idp.authn.IPAddress.supportedPrincipals = \
#idp.authn.Function.order = 1000
#idp.authn.Function.passiveAuthenticationSupported = true
+# Optionally specify list of c14n beans to apply
+#idp.authn.Function.c14n.flows =
# Unset if you plan to return full Java Subject from function
#idp.authn.Function.addDefaultPrincipals = true
@@ -207,6 +224,8 @@ idp.authn.IPAddress.supportedPrincipals = \
# Fall through to discovery via discoveryRequired property
#idp.authn.SAML.proxyEntityID = https://idp.example.org/idp/shibboleth
#idp.authn.SAML.discoveryRequired = true
+# Optionally specify list of c14n beans to apply
+#idp.authn.SAML.c14n.flows =
# Generally left false with bidirectional mappings in
# conf/authn/authn-comparison.xml across the proxy boundary.
# Adjust as needed to reflect IdP's capabilities/support.
@@ -224,6 +243,8 @@ idp.authn.IPAddress.supportedPrincipals = \
#idp.authn.MFA.validateLoginTransitions = true
# Defaults to set AuthnInstant based on oldest component result
#idp.authn.MFA.useLatestTimestamp = false
+# Optionally specify list of c14n beans to apply
+#idp.authn.MFA.c14n.flows =
# The list below almost certainly requires changes, and should generally be the
# union of any of the separate factors you combine in your particular MFA flow
# rules. The example corresponds to the example in mfa-authn-config.xml that
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list