[java-identity-provider] branch main updated: IDP-2091 - Enhance control of AuthnInstant in MFA flow

Scott Cantor cantor.2 at osu.edu
Wed Apr 19 13:40:00 UTC 2023


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=56d57e37a81964aab66b027a36872c0beeb3bfbb

The following commit(s) were added to refs/heads/main by this push:
     new 56d57e37a IDP-2091 - Enhance control of AuthnInstant in MFA flow
56d57e37a is described below

commit 56d57e37a81964aab66b027a36872c0beeb3bfbb
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Apr 19 09:39:57 2023 -0400

    IDP-2091 - Enhance control of AuthnInstant in MFA flow
    
    https://shibboleth.atlassian.net/browse/IDP-2091
---
 .../impl/FinalizeMultiFactorAuthentication.java    | 41 ++++++++++++++++++++--
 .../shibboleth/idp/flows/authn/mfa-authn-beans.xml |  6 +++-
 .../src/main/resources/conf/authn/authn.properties |  2 ++
 3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeMultiFactorAuthentication.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeMultiFactorAuthentication.java
index 229a03060..1f6cff7e3 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeMultiFactorAuthentication.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/FinalizeMultiFactorAuthentication.java
@@ -18,6 +18,7 @@
 package net.shibboleth.idp.authn.impl;
 
 
+import java.time.Instant;
 import java.util.Collection;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
@@ -235,6 +236,21 @@ public class FinalizeMultiFactorAuthentication extends AbstractAuthenticationAct
      */
     public static class DefaultResultMergingStrategy implements Function<ProfileRequestContext,AuthenticationResult> {
 
+        /** Whether to set the authentication time to that of the latest or earliest result. */
+        private boolean latest;
+        
+        /**
+         * Sets whether the final result's timestamp should be based on the latest constituent result.
+         * 
+         * <p>Defaults to false, meaning to use the earliest result's timestamp.</p>
+         * 
+         * @param flag flag to set
+         */
+        public void setUseLatestTimestamp(final boolean flag) {
+            latest = flag;
+        }
+        
+// Checkstyle: CyclomaticComplexity OFF
         /** {@inheritDoc} */
         @Nullable public AuthenticationResult apply(@Nullable final ProfileRequestContext input) {
             
@@ -250,6 +266,9 @@ public class FinalizeMultiFactorAuthentication extends AbstractAuthenticationAct
                             // Track whether SSO was performed.
                             boolean allPreviousResults = true;
                             
+                            // Track timestamp.
+                            Instant ts = null;
+                            
                             final Subject subject = new Subject();
                             for (final AuthenticationResult result : results) {
                                 assert result != null;
@@ -257,7 +276,22 @@ public class FinalizeMultiFactorAuthentication extends AbstractAuthenticationAct
                                 subject.getPrincipals().addAll(result.getSubject().getPrincipals());
                                 subject.getPublicCredentials().addAll(result.getSubject().getPublicCredentials());
                                 subject.getPrivateCredentials().addAll(result.getSubject().getPrivateCredentials());
+                                
                                 allPreviousResults = allPreviousResults && result.isPreviousResult();
+                                
+                                if (ts != null) {
+                                    if (latest) {
+                                        if (result.getAuthenticationInstant().isAfter(ts)) {
+                                            ts = result.getAuthenticationInstant();
+                                        }
+                                    } else {
+                                        if (result.getAuthenticationInstant().isBefore(ts)) {
+                                            ts = result.getAuthenticationInstant();
+                                        }
+                                    }
+                                } else {
+                                    ts = result.getAuthenticationInstant();
+                                }
                             }
                             
                             final AuthenticationFlowDescriptor afd = mfaContext.getAuthenticationFlowDescriptor();
@@ -266,6 +300,9 @@ public class FinalizeMultiFactorAuthentication extends AbstractAuthenticationAct
                             assert afdId != null;
                             final AuthenticationResult merged = new AuthenticationResult(afdId, subject);
                             merged.setPreviousResult(allPreviousResults);
+                            if (ts != null) {
+                                merged.setAuthenticationInstant(ts);
+                            }
                             return merged;
                         }
                     }
@@ -274,7 +311,7 @@ public class FinalizeMultiFactorAuthentication extends AbstractAuthenticationAct
             
             return null;
         }
-        
+// Checkstyle: CyclomaticComplexity ON        
     }
     
-}
+}
\ No newline at end of file
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 b93aa50c2..ea6aef22d 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
@@ -36,9 +36,13 @@
 
     <bean id="FinalizeMultiFactorAuthentication" scope="prototype"
         class="net.shibboleth.idp.authn.impl.FinalizeMultiFactorAuthentication"
-        p:resultMergingStrategy="#{getObject('shibboleth.authn.MFA.resultMergingStrategy')}"
+        p:resultMergingStrategy="#{getObject('shibboleth.authn.MFA.resultMergingStrategy') ?: getObject('DefaultResultMergingStrategy')}"
         p:resultCachingPredicate="#{getObject('shibboleth.authn.MFA.resultCachingPredicate')}" />
 
+    <bean id="DefaultResultMergingStrategy" lazy-init="true"
+        class="net.shibboleth.idp.authn.impl.FinalizeMultiFactorAuthentication.DefaultResultMergingStrategy"
+        p:useLatestTimestamp="%{idp.authn.MFA.useLatestTimestamp:false}" />
+
     <bean id="PopulateSubjectCanonicalizationContext"
         class="net.shibboleth.idp.authn.impl.PopulateSubjectCanonicalizationContext" scope="prototype"
         p:availableFlows-ref="shibboleth.PostLoginSubjectCanonicalizationFlows" />
diff --git a/idp-conf/src/main/resources/conf/authn/authn.properties b/idp-conf/src/main/resources/conf/authn/authn.properties
index cae68f26b..236f2ae37 100644
--- a/idp-conf/src/main/resources/conf/authn/authn.properties
+++ b/idp-conf/src/main/resources/conf/authn/authn.properties
@@ -231,6 +231,8 @@ idp.authn.Duo.supportedPrincipals = \
 #idp.authn.MFA.passiveAuthenticationSupported = true
 #idp.authn.MFA.forcedAuthenticationSupported = true
 #idp.authn.MFA.validateLoginTransitions = true
+# Defaults to set AuthnInstant based on oldest component result
+#idp.authn.MFA.useLatestTimestamp = false
 # 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