[java-identity-provider] branch main updated: IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
Scott Cantor
cantor.2 at osu.edu
Wed Mar 12 15:39:48 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=a14cede77d43c90569f68051ba0706d8baaf6afe
The following commit(s) were added to refs/heads/main by this push:
new a14cede77 IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
a14cede77 is described below
commit a14cede77d43c90569f68051ba0706d8baaf6afe
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Mar 12 11:39:42 2025 -0400
IDP-2351 - Allow per-AuthenticationResult lifetime/timeout policies
https://shibboleth.atlassian.net/browse/IDP-2351
Implement support via External method.
---
.../idp/authn/AbstractValidationAction.java | 7 ++-
.../idp/authn/ExternalAuthentication.java | 19 +++++-
.../context/ExternalAuthenticationContext.java | 60 ++++++++++++++++++
.../idp/authn/impl/ExternalAuthenticationImpl.java | 71 ++++++++++------------
.../authn/impl/ValidateExternalAuthentication.java | 20 +++---
5 files changed, 126 insertions(+), 51 deletions(-)
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..14e20e72a 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
@@ -385,8 +385,11 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
*
* @param profileRequestContext the current profile request context
* @param authenticationContext the current authentication context
+ *
+ * @return the new result
*/
- protected void buildAuthenticationResult(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull protected AuthenticationResult buildAuthenticationResult(
+ @Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final AuthenticationContext authenticationContext) {
final AuthenticationFlowDescriptor attemptedFlow = authenticationContext.getAttemptedFlow();
@@ -424,6 +427,8 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
Constraint.isNotNull(authenticationContext.getParent(),
"Parent context cannot be null").addSubcontext(c14n, true);
+
+ return result;
}
/**
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
index 91bdb03c6..476d5f86e 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/ExternalAuthentication.java
@@ -58,13 +58,27 @@ public abstract class ExternalAuthentication {
/** Request attribute to which an authentication timestamp may be bound. */
@Nonnull @NotEmpty public static final String AUTHENTICATION_INSTANT_KEY = "authnInstant";
+ /**
+ * Request attribute to which the authentication result lifetime may be bound.
+ *
+ * @since 5.2.0
+ */
+ @Nonnull @NotEmpty public static final String RESULT_LIFETIME_KEY = "authnLifetime";
+
+ /**
+ * Request attribute to which the authentication result timeout may be bound.
+ *
+ * @since 5.2.0
+ */
+ @Nonnull @NotEmpty public static final String RESULT_TIMEOUT_KEY = "authnTimeout";
+
/**
* Request attribute to which a collection of authenticating authorities may be bound.
*
* @since 3.4.0
*/
@Nonnull @NotEmpty public static final String AUTHENTICATING_AUTHORITIES_KEY = "authnAuthorities";
-
+
/**
* Request attribute to which a collection of {@link IdPAttribute} objects may be bound.
*
@@ -94,7 +108,7 @@ public abstract class ExternalAuthentication {
* @since 3.2.0
*/
@Nonnull @NotEmpty public static final String REVOKECONSENT_KEY = "revokeConsent";
-
+
/**
* Request attribute to which a signal to set
* {@link net.shibboleth.idp.authn.AuthenticationResult#setPreviousResult(boolean)} may be bound.
@@ -111,6 +125,7 @@ public abstract class ExternalAuthentication {
/** Request attribute that provides the entity ID of the relying party that is requesting authentication. */
@Nonnull @NotEmpty public static final String RELYING_PARTY_PARAM = "relyingParty";
+
/**
* Request attribute that indicates whether we're being called as an extension of another login flow.
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
index 781570349..74f32e44a 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/ExternalAuthenticationContext.java
@@ -15,6 +15,7 @@
package net.shibboleth.idp.authn.context;
import java.security.Principal;
+import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
@@ -25,6 +26,7 @@ import javax.security.auth.Subject;
import org.opensaml.messaging.context.BaseContext;
+import net.shibboleth.idp.authn.AuthenticationResult;
import net.shibboleth.idp.authn.ExternalAuthentication;
import net.shibboleth.shared.annotation.constraint.Live;
import net.shibboleth.shared.logic.Constraint;
@@ -56,6 +58,12 @@ public final class ExternalAuthenticationContext extends BaseContext {
/** Time of authentication. */
@Nullable private Instant authnInstant;
+ /** Override for result lifetime. */
+ @Nullable private Duration authnLifetime;
+
+ /** Override for result timeout. */
+ @Nullable private Duration authnTimeout;
+
/** Proxied authenticating sources. */
@Nonnull private Collection<String> authenticatingAuthorities;
@@ -206,6 +214,58 @@ public final class ExternalAuthenticationContext extends BaseContext {
return this;
}
+ /**
+ * Get a custom lifetime to apply to the built {@link AuthenticationResult}.
+ *
+ * @return override of result lifetime
+ *
+ * @since 5.2.0
+ */
+ @Nullable public Duration getAuthnLifetime() {
+ return authnLifetime;
+ }
+
+ /**
+ * Set a custom lifetime to apply to the built {@link AuthenticationResult}.
+ *
+ * @param lifetime override of result lifetime
+ *
+ * @return this context
+ *
+ * @since 5.2.0
+ */
+ @Nonnull public ExternalAuthenticationContext setAuthnLifetime(@Nullable final Duration lifetime) {
+ authnLifetime = lifetime;
+
+ return this;
+ }
+
+ /**
+ * Get a custom timeout to apply to the built {@link AuthenticationResult}.
+ *
+ * @return override of result timeout
+ *
+ * @since 5.2.0
+ */
+ @Nullable public Duration getAuthnTimeout() {
+ return authnTimeout;
+ }
+
+ /**
+ * Set a custom timeout to apply to the built {@link AuthenticationResult}.
+ *
+ * @param timeout override of result timeout
+ *
+ * @return this context
+ *
+ * @since 5.2.0
+ */
+ @Nonnull public ExternalAuthenticationContext setAuthnTimeout(@Nullable final Duration timeout) {
+ authnTimeout = timeout;
+
+ return this;
+ }
+
/**
* Get a mutable, ordered list of proxied authentication sources.
*
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
index d2e02e1b1..fa08db859 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ExternalAuthenticationImpl.java
@@ -16,6 +16,7 @@ package net.shibboleth.idp.authn.impl;
import java.io.IOException;
import java.security.Principal;
+import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.function.Function;
@@ -115,67 +116,61 @@ public class ExternalAuthenticationImpl extends ExternalAuthentication {
throw new ExternalAuthenticationException("No flow execution URL found to return control");
}
- Object attr = request.getAttribute(SUBJECT_KEY);
- if (attr != null && attr instanceof Subject) {
- extContext.setSubject((Subject) attr);
+ if (request.getAttribute(SUBJECT_KEY) instanceof Subject sub) {
+ extContext.setSubject(sub);
} else {
- attr = request.getAttribute(PRINCIPAL_KEY);
- if (attr != null && attr instanceof Principal) {
- extContext.setPrincipal((Principal) attr);
+ if (request.getAttribute(PRINCIPAL_KEY) instanceof Principal prin) {
+ extContext.setPrincipal(prin);
} else {
- attr = request.getAttribute(PRINCIPAL_NAME_KEY);
- if (attr != null && attr instanceof String) {
- extContext.setPrincipalName((String) attr);
+ if (request.getAttribute(PRINCIPAL_NAME_KEY) instanceof String s) {
+ extContext.setPrincipalName(s);
}
}
}
- attr = request.getAttribute(AUTHENTICATION_INSTANT_KEY);
- if (attr != null && attr instanceof Instant) {
- extContext.setAuthnInstant((Instant) attr);
+ if (request.getAttribute(AUTHENTICATION_INSTANT_KEY) instanceof Instant ts) {
+ extContext.setAuthnInstant(ts);
}
- attr = request.getAttribute(AUTHENTICATING_AUTHORITIES_KEY);
- if (attr != null && attr instanceof Collection<?>) {
- extContext.getAuthenticatingAuthorities().addAll((Collection<String>) attr);
+ if (request.getAttribute(RESULT_LIFETIME_KEY) instanceof Duration dur) {
+ extContext.setAuthnLifetime(dur);
+ }
+
+ if (request.getAttribute(RESULT_TIMEOUT_KEY) instanceof Duration dur) {
+ extContext.setAuthnTimeout(dur);
+ }
+
+ if (request.getAttribute(AUTHENTICATING_AUTHORITIES_KEY) instanceof Collection<?> c) {
+ extContext.getAuthenticatingAuthorities().addAll((Collection<String>) c);
}
- attr = request.getAttribute(ATTRIBUTES_KEY);
- if (attr != null && attr instanceof Collection<?>) {
+ if (request.getAttribute(ATTRIBUTES_KEY) instanceof Collection<?> attrs) {
final AttributeContext ac = extContext.ensureSubcontext(AttributeContext.class);
- ac.setUnfilteredIdPAttributes(
- (Collection<IdPAttribute>) attr);
- ac.setIdPAttributes(
- (Collection<IdPAttribute>) attr);
+ ac.setUnfilteredIdPAttributes((Collection<IdPAttribute>) attrs);
+ ac.setIdPAttributes((Collection<IdPAttribute>) attrs);
}
- attr = request.getAttribute(AUTHENTICATION_ERROR_KEY);
- if (attr != null && attr instanceof String) {
- extContext.setAuthnError((String) attr);
+ if (request.getAttribute(AUTHENTICATION_ERROR_KEY) instanceof String s) {
+ extContext.setAuthnError(s);
}
- attr = request.getAttribute(AUTHENTICATION_EXCEPTION_KEY);
- if (attr != null && attr instanceof Exception) {
- extContext.setAuthnException((Exception) attr);
+ if (request.getAttribute(AUTHENTICATION_EXCEPTION_KEY) instanceof Exception e) {
+ extContext.setAuthnException(e);
}
- attr = request.getAttribute(AUTHENTICATION_EVENT_KEY);
- if (attr != null && attr instanceof String) {
- extContext.setAuthnEvent((String) attr);
+ if (request.getAttribute(AUTHENTICATION_EVENT_KEY) instanceof String s) {
+ extContext.setAuthnEvent(s);
}
- attr = request.getAttribute(DONOTCACHE_KEY);
- if (attr != null && attr instanceof Boolean) {
- extContext.setDoNotCache((Boolean) attr);
+ if (request.getAttribute(DONOTCACHE_KEY) instanceof Boolean flag) {
+ extContext.setDoNotCache(flag);
}
- attr = request.getAttribute(PREVIOUSRESULT_KEY);
- if (attr != null && attr instanceof Boolean) {
- extContext.setPreviousResult((Boolean) attr);
+ if (request.getAttribute(PREVIOUSRESULT_KEY) instanceof Boolean flag) {
+ extContext.setPreviousResult(flag);
}
- attr = request.getAttribute(REVOKECONSENT_KEY);
- if (attr != null && attr instanceof Boolean && ((Boolean) attr).booleanValue()) {
+ if (request.getAttribute(REVOKECONSENT_KEY) instanceof Boolean flag && flag.booleanValue()) {
final ConsentManagementContext consentCtx =
profileRequestContext.ensureSubcontext(ConsentManagementContext.class);
consentCtx.setRevokeConsent(true);
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
index 6e0cf2d6e..e387d52fa 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/ValidateExternalAuthentication.java
@@ -243,17 +243,17 @@ public class ValidateExternalAuthentication extends AbstractAuditingValidationAc
assert extContext != null;
filterAttributes(extContext);
- buildAuthenticationResult(profileRequestContext, authenticationContext);
+ final AuthenticationResult result = buildAuthenticationResult(profileRequestContext, authenticationContext);
+ final Instant ai = extContext.getAuthnInstant();
+ if (ai != null) {
+ result.setAuthenticationInstant(ai);
+ }
- final AuthenticationResult ar = authenticationContext.getAuthenticationResult();
- if (ar != null) {
- final Instant ai = extContext.getAuthnInstant();
- if (ai != null) {
- ar.setAuthenticationInstant(ai);
- }
- if (extContext.isPreviousResult()) {
- ar.setPreviousResult(true);
- }
+ result.setResultLifetime(extContext.getAuthnLifetime());
+ result.setResultTimeout(extContext.getAuthnTimeout());
+
+ if (extContext.isPreviousResult()) {
+ result.setPreviousResult(true);
}
}
// Checkstyle: ReturnCount|CyclomaticComplexity|MethodLength ON
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list