[java-identity-provider] branch main updated: IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
Scott Cantor
cantor.2 at osu.edu
Wed Mar 19 16:28:44 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=f07b66708e8968ec0762975a7a65e6798dceabaf
The following commit(s) were added to refs/heads/main by this push:
new f07b66708 IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
f07b66708 is described below
commit f07b66708e8968ec0762975a7a65e6798dceabaf
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Mar 19 12:28:41 2025 -0400
IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
https://shibboleth.atlassian.net/browse/IDP-2351
Added flow descriptor and property support for control via strategies.
---
.../idp/authn/AbstractValidationAction.java | 3 ++
.../idp/authn/AuthenticationFlowDescriptor.java | 62 ++++++++++++++++++++++
.../net/shibboleth/idp/conf/authn-system.xml | 28 ++++++++++
3 files changed, 93 insertions(+)
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractValidationAction.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractValidationAction.java
index 1a19ffcca..b7c43b13c 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractValidationAction.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AbstractValidationAction.java
@@ -407,6 +407,9 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
authenticationContext.isResultCacheable() ? "will" : "will not");
}
+ result.setResultLifetime(attemptedFlow.getResultLifetimeLookupStrategy().apply(profileRequestContext));
+ result.setResultTimeout(attemptedFlow.getResultTimeoutLookupStrategy().apply(profileRequestContext));
+
final BiConsumer<ProfileRequestContext,Subject> decorator = attemptedFlow.getSubjectDecorator();
if (decorator != null) {
decorator.accept(profileRequestContext, result.getSubject());
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
index 62c6ec7a8..90576c3fe 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/AuthenticationFlowDescriptor.java
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
+import java.util.function.Function;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
@@ -48,6 +49,7 @@ import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
import net.shibboleth.shared.logic.PredicateSupport;
import net.shibboleth.shared.primitive.StringSupport;
@@ -103,6 +105,12 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
/** Maximum amount of time since last usage that a flow should be considered active. */
@Nonnull private Duration inactivityTimeout;
+ /** Lookup strategy for per-result lifetime. */
+ @Nonnull private Function<ProfileRequestContext,Duration> resultLifetimeLookupStrategy;
+
+ /** Lookup strategy for per-result timeout. */
+ @Nonnull private Function<ProfileRequestContext,Duration> resultTimeoutLookupStrategy;
+
/**
* Supported principals provided by delimited strings, for post-initialization override via
* {@link PrincipalServiceManager}.
@@ -136,6 +144,8 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
supportsNonBrowser = true;
proxyRestrictionsEnforced = true;
reuseCondition = new ProxyCountPredicate();
+ resultLifetimeLookupStrategy = FunctionSupport.constant(null);
+ resultTimeoutLookupStrategy = FunctionSupport.constant(null);
supportedPrincipals = new Subject();
activationCondition = PredicateSupport.alwaysTrue();
final Duration thirtyMins = Duration.ofMinutes(30);
@@ -424,6 +434,58 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
inactivityTimeout = timeout;
}
+
+ /**
+ * Get the lookup strategy to compute a per-result lifetime to apply to a given result.
+ *
+ * @return lookup strategy
+ *
+ * @since 5.2.0
+ */
+ @Nonnull public Function<ProfileRequestContext,Duration> getResultLifetimeLookupStrategy() {
+ return resultLifetimeLookupStrategy;
+ }
+
+ /**
+ * Set the lookup strategy to compute a per-result lifetime to apply to a given result.
+ *
+ * <p>Defaults to returning null, deferring to flow default.</p>
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 5.2.0
+ */
+ public void setResultLifetimeLookupStrategy(@Nonnull final Function<ProfileRequestContext,Duration> strategy) {
+ checkSetterPreconditions();
+ resultLifetimeLookupStrategy =
+ Constraint.isNotNull(strategy, "AuthenticationResult lifetime lookup strategy cannot be null");
+ }
+
+ /**
+ * Get the lookup strategy to compute a per-result timeout to apply to a given result.
+ *
+ * @return lookup strategy
+ *
+ * @since 5.2.0
+ */
+ @Nonnull public Function<ProfileRequestContext,Duration> getResultTimeoutLookupStrategy() {
+ return resultTimeoutLookupStrategy;
+ }
+
+ /**
+ * Set the lookup strategy to compute a per-result timeout to apply to a given result.
+ *
+ * <p>Defaults to returning null, deferring to flow default.</p>
+ *
+ * @param strategy lookup strategy
+ *
+ * @since 5.2.0
+ */
+ public void setResultTimeoutLookupStrategy(@Nonnull final Function<ProfileRequestContext,Duration> strategy) {
+ checkSetterPreconditions();
+ resultTimeoutLookupStrategy =
+ Constraint.isNotNull(strategy, "AuthenticationResult timeout lookup strategy cannot be null");
+ }
/**
* Check if a result generated by this flow is still active.
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
index 763539d01..ddfa70a4a 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/authn-system.xml
@@ -41,6 +41,12 @@
</property>
</bean>
+ <bean id="NullDurationLookupStrategy" parent="shibboleth.Functions.Constant">
+ <constructor-arg>
+ <null/>
+ </constructor-arg>
+ </bean>
+
<!-- Defaulted flows. -->
<bean p:id="authn/Password" parent="shibboleth.AuthenticationFlow"
@@ -55,6 +61,8 @@
p:inactivityTimeout="%{idp.authn.Password.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.Password.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.Password.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.Password.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.Password.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.Password.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -74,6 +82,8 @@
p:inactivityTimeout="%{idp.authn.IPAddress.inactivityTimeout:PT60S}"
p:reuseCondition-ref="#{'%{idp.authn.IPAddress.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.IPAddress.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.IPAddress.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.IPAddress.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.IPAddress.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -93,6 +103,8 @@
p:inactivityTimeout="%{idp.authn.Function.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.Function.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.Function.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.Function.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.Function.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.Function.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -112,6 +124,8 @@
p:inactivityTimeout="%{idp.authn.External.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.External.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.External.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.External.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.External.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.External.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -131,6 +145,8 @@
p:inactivityTimeout="%{idp.authn.RemoteUser.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.RemoteUser.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.RemoteUser.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.RemoteUser.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.RemoteUser.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.RemoteUser.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -150,6 +166,8 @@
p:inactivityTimeout="%{idp.authn.RemoteUserInternal.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.RemoteUserInternal.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.RemoteUserInternal.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.RemoteUserInternal.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.RemoteUserInternal.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.RemoteUserInternal.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -169,6 +187,8 @@
p:inactivityTimeout="%{idp.authn.SAML.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.SAML.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.SAML.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.SAML.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.SAML.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.SAML.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -188,6 +208,8 @@
p:inactivityTimeout="%{idp.authn.SPNEGO.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.SPNEGO.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.SPNEGO.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.SPNEGO.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.SPNEGO.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.SPNEGO.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -207,6 +229,8 @@
p:inactivityTimeout="%{idp.authn.X509.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.X509.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.X509.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.X509.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.X509.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.X509.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -226,6 +250,8 @@
p:inactivityTimeout="%{idp.authn.X509Internal.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.X509Internal.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.X509Internal.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.X509Internal.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.X509Internal.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.X509Internal.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
@@ -245,6 +271,8 @@
p:inactivityTimeout="%{idp.authn.MFA.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
p:reuseCondition-ref="#{'%{idp.authn.MFA.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
p:activationCondition-ref="#{'%{idp.authn.MFA.activationCondition:shibboleth.Conditions.TRUE}'.trim()}"
+ p:resultLifetimeLookupStrategy-ref="#{'%{idp.authn.MFA.lifetimeStrategy:NullDurationLookupStrategy}'.trim()}"
+ p:resultTimeoutLookupStrategy-ref="#{'%{idp.authn.MFA.inactivityTimeoutStrategy:NullDurationLookupStrategy}'.trim()}"
p:subjectDecorator="#{getObject('%{idp.authn.MFA.subjectDecorator:}'.trim())}">
<property name="supportedPrincipalsByString">
<bean parent="shibboleth.CommaDelimStringArray"
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list