[java-identity-provider] branch main updated: IDP-2074 - Audit logging of chained password validators is broken

Scott Cantor cantor.2 at osu.edu
Tue Apr 18 13:55:30 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=883530bcadc896a14fc7c3f424e15a0ac4bee413

The following commit(s) were added to refs/heads/main by this push:
     new 883530bca IDP-2074 - Audit logging of chained password validators is broken
883530bca is described below

commit 883530bcadc896a14fc7c3f424e15a0ac4bee413
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Apr 18 09:55:26 2023 -0400

    IDP-2074 - Audit logging of chained password validators is broken
    
    https://shibboleth.atlassian.net/browse/IDP-2074
    
    Adjusted context APIs to allow tracking of last error/warning.
    Removed Spring-based handling of AR audit field.
    Manually added AR field to audit context via auditing validation action.
---
 .../idp/authn/AbstractValidationAction.java        |  11 +-
 .../authn/context/AuthenticationErrorContext.java  |  48 ++--
 .../context/AuthenticationWarningContext.java      |  33 ++-
 .../impl/AuthenticationErrorAuditExtractor.java    |  56 -----
 .../impl/AbstractAuditingValidationAction.java     |  33 ++-
 .../idp/flows/authn/authn-abstract-beans.xml       |   6 -
 .../src/test/resources/conf/authn/authn.properties | 243 +++++++++++++++++++++
 7 files changed, 334 insertions(+), 96 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 7b6a3df52..7e3a0ac22 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
@@ -528,8 +528,7 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
                 if (Iterables.any(entry.getValue(), checker::test)) {
                     final String key = entry.getKey();
                     assert key!=null;
-                    authenticationContext.ensureSubcontext(
-                            AuthenticationErrorContext.class).getClassifiedErrors().add(key);
+                    authenticationContext.ensureSubcontext(AuthenticationErrorContext.class).addClassifiedError(key);
                     if (!eventSet) {
                         eventSet = true;
                         ActionSupport.buildEvent(profileRequestContext, key);
@@ -539,8 +538,7 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
         }
         
         if (!eventSet) {
-            authenticationContext.ensureSubcontext(
-                    AuthenticationErrorContext.class).getClassifiedErrors().add(eventId);
+            authenticationContext.ensureSubcontext(AuthenticationErrorContext.class).addClassifiedError(eventId);
             ActionSupport.buildEvent(profileRequestContext, eventId);
         }
     }
@@ -575,7 +573,7 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
                     final String key = entry.getKey();
                     assert key!=null;
                     authenticationContext.ensureSubcontext(
-                            AuthenticationWarningContext.class).getClassifiedWarnings().add(key);
+                            AuthenticationWarningContext.class).addClassifiedWarning(key);
                     if (!eventSet) {
                         eventSet = true;
                         ActionSupport.buildEvent(profileRequestContext, key);
@@ -585,8 +583,7 @@ public abstract class AbstractValidationAction extends AbstractAuthenticationAct
         }
         
         if (!eventSet) {
-            authenticationContext.ensureSubcontext(
-                    AuthenticationWarningContext.class).getClassifiedWarnings().add(eventId);
+            authenticationContext.ensureSubcontext(AuthenticationWarningContext.class).addClassifiedWarning(eventId);
             ActionSupport.buildEvent(profileRequestContext, eventId);
         }
     }
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationErrorContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationErrorContext.java
index 80a7b3570..fe4eff372 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationErrorContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationErrorContext.java
@@ -19,15 +19,15 @@ package net.shibboleth.idp.authn.context;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import net.shibboleth.shared.annotation.constraint.Live;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
 
 import org.opensaml.messaging.context.BaseContext;
 
@@ -53,7 +53,7 @@ public final class AuthenticationErrorContext extends BaseContext {
     /** Constructor. */
     public AuthenticationErrorContext() {
         exceptions = new ArrayList<>();
-        classifiedErrors = new HashSet<>();
+        classifiedErrors = new LinkedHashSet<>();
     }
 
     /**
@@ -65,20 +65,6 @@ public final class AuthenticationErrorContext extends BaseContext {
         return exceptions;
     }
     
-    /**
-     * Add an exception to the list.
-     * 
-     * @param e exception to add
-     * 
-     * @deprecated
-     */
-    @Deprecated(forRemoval=true, since="4.0.0")
-    public void addException(@Nonnull final Exception e) {
-        Constraint.isNotNull(e, "Exception cannot be null");
-        
-        exceptions.add(e);
-    }
-    
     /**
      * Get a mutable collection of error "tokens" associated with the context.
      * 
@@ -98,4 +84,32 @@ public final class AuthenticationErrorContext extends BaseContext {
         return classifiedErrors.contains(error);
     }
     
+    /**
+     * Adds a classified error to the context, ensuring that it will be returned
+     * from {@link #getLastClassifiedError()} until another is added.
+     * 
+     * @param error error to add
+     * 
+     * @return this context
+     * 
+     * @since 5.0.0
+     */
+    @Nonnull public AuthenticationErrorContext addClassifiedError(@Nonnull @NotEmpty final String error) {
+        // This is done to preserve ordering so that the error is the "last one added".
+        classifiedErrors.remove(error);
+        classifiedErrors.add(error);
+        return this;
+    }
+    
+    /**
+     * Gets the last classified error added, or null if none.
+     * 
+     * @return last error added or null
+     * 
+     * @since 5.0.0
+     */
+    @Nullable public String getLastClassifiedError() {
+        return classifiedErrors.stream().reduce((first, second) -> second).orElse(null);
+    }
+    
 }
\ No newline at end of file
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationWarningContext.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationWarningContext.java
index 13a39bd83..0963dbbc6 100644
--- a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationWarningContext.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/context/AuthenticationWarningContext.java
@@ -18,9 +18,10 @@
 package net.shibboleth.idp.authn.context;
 
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.opensaml.messaging.context.BaseContext;
 
@@ -46,7 +47,7 @@ public final class AuthenticationWarningContext extends BaseContext {
     
     /** Constructor. */
     public AuthenticationWarningContext() {
-        classifiedWarnings = new HashSet<>();
+        classifiedWarnings = new LinkedHashSet<>();
     }
 
     /**
@@ -68,4 +69,32 @@ public final class AuthenticationWarningContext extends BaseContext {
         return classifiedWarnings.contains(warning);
     }
 
+    /**
+     * Adds a classified warning to the context, ensuring that it will be returned
+     * from {@link #getLastClassifiedWarning()} until another is added.
+     * 
+     * @param warning warning to add
+     * 
+     * @return this context
+     * 
+     * @since 5.0.0
+     */
+    @Nonnull public AuthenticationWarningContext addClassifiedWarning(@Nonnull @NotEmpty final String warning) {
+        // This is done to preserve ordering so that the error is the "last one added".
+        classifiedWarnings.remove(warning);
+        classifiedWarnings.add(warning);
+        return this;
+    }
+    
+    /**
+     * Gets the last classified warning added, or null if none.
+     * 
+     * @return last warning added or null
+     * 
+     * @since 5.0.0
+     */
+    @Nullable public String getLastClassifiedWarning() {
+        return classifiedWarnings.stream().reduce((first, second) -> second).orElse(null);
+    }
+
 }
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AuthenticationErrorAuditExtractor.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AuthenticationErrorAuditExtractor.java
deleted file mode 100644
index f6b09870e..000000000
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/audit/impl/AuthenticationErrorAuditExtractor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the University Corporation for Advanced Internet Development,
- * Inc. (UCAID) under one or more contributor license agreements.  See the
- * NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The UCAID licenses this file to You 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.audit.impl;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.function.Function;
-
-import javax.annotation.Nullable;
-
-import org.opensaml.profile.context.ProfileRequestContext;
-
-import net.shibboleth.idp.authn.context.AuthenticationContext;
-import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
-
-/**
- * {@link Function} that returns any classified errors found in a subordinate {@link AuthenticationErrorContext},
- * or "Success" if none.
- * 
- * @since 4.3.0
- */
-public class AuthenticationErrorAuditExtractor implements Function<ProfileRequestContext,Collection<String>> {
-
-    /** {@inheritDoc} */
-    @Nullable public Collection<String> apply(@Nullable final ProfileRequestContext input) {
-
-        assert input != null;
-        final AuthenticationContext authnCtx = input.getSubcontext(AuthenticationContext.class);
-        if (authnCtx != null) {
-            final AuthenticationErrorContext errorCtx = authnCtx.getSubcontext(AuthenticationErrorContext.class);
-            if (errorCtx != null) {
-                return errorCtx.getClassifiedErrors();
-            }
-            
-            return Collections.singletonList("Success");
-        }
-        
-        return null;
-    }
-    
-}
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AbstractAuditingValidationAction.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AbstractAuditingValidationAction.java
index 7592bbe57..ad3a76a55 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AbstractAuditingValidationAction.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AbstractAuditingValidationAction.java
@@ -30,7 +30,9 @@ import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
 import net.shibboleth.idp.authn.AbstractValidationAction;
+import net.shibboleth.idp.authn.AuthnAuditFields;
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
 import net.shibboleth.idp.profile.audit.impl.PopulateAuditContext;
 import net.shibboleth.idp.profile.audit.impl.WriteAuditLog;
 import net.shibboleth.profile.context.AuditContext;
@@ -114,14 +116,14 @@ public abstract class AbstractAuditingValidationAction extends AbstractValidatio
     /** {@inheritDoc} */
     @Override
     protected void recordSuccess(@Nonnull final ProfileRequestContext profileRequestContext) {
-        doAudit(profileRequestContext);
+        doAudit(profileRequestContext, true);
         super.recordSuccess(profileRequestContext);
     }
 
     /** {@inheritDoc} */
     @Override
     protected void recordFailure(@Nonnull final ProfileRequestContext profileRequestContext) {
-        doAudit(profileRequestContext);
+        doAudit(profileRequestContext, false);
         super.recordFailure(profileRequestContext);
     }
     
@@ -136,12 +138,14 @@ public abstract class AbstractAuditingValidationAction extends AbstractValidatio
         return auditContextCreationStrategy.apply(profileRequestContext);
     }
     
+// Checkstyle: CyclomaticComplexity OFF
     /**
      * Do audit extraction and output.
      * 
      * @param profileRequestContext profile request context
+     * @param success true iff this is an audit of successful validation
      */
-    protected void doAudit(@Nonnull final ProfileRequestContext profileRequestContext) {
+    protected void doAudit(@Nonnull final ProfileRequestContext profileRequestContext, final boolean success) {
 
         if (populateAuditContextAction != null && writeAuditLogAction != null) {
             final EventContext existingEvent = profileRequestContext.getSubcontext(EventContext.class);
@@ -149,17 +153,29 @@ public abstract class AbstractAuditingValidationAction extends AbstractValidatio
             try {
                 assert populateAuditContextAction != null;
                 populateAuditContextAction.execute(requestContext);
-                
-                final Map<String,String> fields = getAuditFields(profileRequestContext);
-                if (fields != null) {
-                    final AuditContext ac = getAuditContext(profileRequestContext);
-                    if (ac != null) {
+
+                final AuditContext ac = getAuditContext(profileRequestContext);
+                if (ac != null) {
+                    final Map<String,String> fields = getAuditFields(profileRequestContext);
+                    if (fields != null) {
                         for (final Map.Entry<String,String> field : fields.entrySet()) {
                             final String key = field.getKey();
                             assert key != null;
                             ac.getFieldValues(key).add(field.getValue());
                         }
                     }
+                    
+                    // Manual handling of "result" field.
+                    if (success) {
+                        ac.getFields().put(AuthnAuditFields.AUTHN_RESULT, "Success");
+                    } else {
+                        final AuthenticationErrorContext errorContext =
+                                profileRequestContext.ensureSubcontext(AuthenticationContext.class)
+                                    .getSubcontext(AuthenticationErrorContext.class);
+                        if (errorContext != null) {
+                            ac.getFields().put(AuthnAuditFields.AUTHN_RESULT, errorContext.getLastClassifiedError());
+                        }
+                    }
                 }
             } finally {
                 if (existingEvent != null) {
@@ -177,6 +193,7 @@ public abstract class AbstractAuditingValidationAction extends AbstractValidatio
             }
         }
     }
+// Checkstyle: CyclomaticComplexity ON
     
     /**
      * Subclasses can override this method to supply additional audit fields to store.
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/authn-abstract-beans.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/authn-abstract-beans.xml
index b511f0e2a..7207955f5 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/authn-abstract-beans.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/flows/authn/authn-abstract-beans.xml
@@ -68,12 +68,6 @@
                     </key>
                     <bean class="net.shibboleth.idp.authn.audit.impl.AttemptedAuthenticationFlowAuditExtractor" />
                 </entry>
-                <entry>
-                    <key>
-                        <util:constant static-field="net.shibboleth.idp.authn.AuthnAuditFields.AUTHN_RESULT"/>
-                    </key>
-                    <bean class="net.shibboleth.idp.authn.audit.impl.AuthenticationErrorAuditExtractor" />
-                </entry>
                 <entry>
                     <key>
                         <util:constant static-field="net.shibboleth.idp.saml.profile.SAMLAuditFields.SERVICE_PROVIDER"/>
diff --git a/idp-conf/src/test/resources/conf/authn/authn.properties b/idp-conf/src/test/resources/conf/authn/authn.properties
new file mode 100644
index 000000000..6b029e14d
--- /dev/null
+++ b/idp-conf/src/test/resources/conf/authn/authn.properties
@@ -0,0 +1,243 @@
+# Properties that control authentication generally and the behavior of
+# specific methods.
+
+# Regular expression matching login flows to enable, e.g. IPAddress|Password
+#idp.authn.flows = Password
+
+# Default settings for most authentication methods.
+#idp.authn.defaultLifetime = PT1H
+#idp.authn.defaultTimeout = PT30M
+#idp.authn.proxyRestrictionsEnforced = true
+
+# Whether to populate relying party user interface information for display
+# during authentication, consent, terms-of-use.
+#idp.authn.rpui = true
+
+# Whether to prioritize "active" results when an SP requests more than
+# one possible matching login method (V2 behavior was to favor them)
+#idp.authn.favorSSO = false
+
+# Whether to fail requests when a user identity after authentication
+# doesn't match the identity in a pre-existing session.
+#idp.authn.identitySwitchIsError = false
+
+# If using IdP discovery feature, provides a discovery location to use.
+#idp.authn.discoveryURL = https://ds.example.org/shibboleth-ds/index.html
+
+# Login flow audit logging (defaults false for log compatibility)
+idp.authn.audit.enabled = true
+
+# Revocation (administrative logout)
+#idp.authn.revocation = false
+#idp.authn.revocation.lifetime = %{idp.authn.defaultAuthnLifetime:PT12H}
+# Name of BiCondition to apply for check
+#idp.authn.revocation.Condition = shibboleth.RevocationCacheCondition
+# Set to true to treat lookup failures as being revoked.
+#idp.authn.revocation.strict = false
+# Set to true to check for address-based revocation.
+#idp.authn.revocation.addressBased = false
+# Default implementation based on a StorageService bean.
+#idp.authn.revocation.cache = shibboleth.AuthnRevocationCache
+#idp.authn.revocation.StorageService = shibboleth.StorageService
+
+
+# Properties below override specific method behavior, as an alternative
+# to defining Spring beans in XML. Refer to the documentation for a complete
+# list. Many of the properties below are mentioned only because they are
+# atypical defaults assumed for a given method.
+
+# Flow selection among multiple equivalent options can be managed with
+# the order properties, lower will be tried first.
+
+#### Password ####
+
+#idp.authn.Password.order = 1000
+#idp.authn.Password.passiveAuthenticationSupported = true
+#idp.authn.Password.forcedAuthenticationSupported = true
+# Override this and removeAfterValidation to require all validators to succeed
+#idp.authn.Password.requireAll = false
+# Override to keep the password around
+#idp.authn.Password.removeAfterValidation = true
+# Override to store password in Java Subject
+#idp.authn.Password.retainAsPrivateCredential = false
+# Simple username transforms before validation
+#idp.authn.Password.trim = true
+#idp.authn.Password.lowercase = false
+#idp.authn.Password.uppercase = false
+#idp.authn.Password.matchExpression = 
+# Override default form field names
+#idp.authn.Password.usernameFieldName = j_username
+#idp.authn.Password.passwordFieldName = j_password
+#idp.authn.Password.ssoBypassFieldName = donotcache
+# Unset if using customized Principals per validator
+#idp.authn.Password.addDefaultPrincipals = true
+# The Principal collection below is the typical default if not otherwise noted.
+#idp.authn.Password.supportedPrincipals = \
+#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \
+#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \
+#    saml1/urn:oasis:names:tc:SAML:1.0:am:password
+# Validators are controlled in password-authn-config.xml
+
+#### Password Backends ####
+
+# See ldap.properties for LDAP authn properties
+# Kerberos settings
+#idp.authn.Krb5.refreshConfig = false
+#idp.authn.Krb5.preserveTicket = false
+# Set next two for KDC verification
+#idp.authn.Krb5.servicePrincipal = 
+#idp.authn.Krb5.keytab = 
+# JAAS settings
+#idp.authn.JAAS.loginConfigNames = ShibUserPassAuth
+#idp.authn.JAAS.loginConfig = %{idp.home}/conf/authn/jaas.config
+
+#### External ####
+
+#idp.authn.External.order = 1000
+#idp.authn.External.nonBrowserSupported = false
+#idp.authn.External.matchExpression = 
+# Unset if you plan to return full Java Subject from external source
+#idp.authn.External.addDefaultPrincipals = true
+# Servlet context-relative path to wherever your implementation lives
+idp.authn.External.externalAuthnPath = contextRelative:external.jsp
+
+#### RemoteUser ####
+
+#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
+#idp.authn.RemoteUser.addDefaultPrincipals = true
+#idp.authn.RemoteUser.checkRemoteUser = true
+# Comma-delimited lists of attributes or headers to pull from
+#idp.authn.RemoteUser.checkAttributes = 
+#idp.authn.RemoteUser.checkHeaders = 
+# Advanced settings
+#idp.authn.RemoteUser.subjectAttribute =
+#idp.authn.RemoteUser.authnMethodHeader =
+#idp.authn.RemoteUser.authnAuthorityHeader =
+
+#### RemoteUserInternal ####
+
+#idp.authn.RemoteUserInternal.order = 1000
+#idp.authn.RemoteUserInternal.nonBrowserSupported = true
+# Unset in most cases only if using the authnMethodHeader feature
+#idp.authn.RemoteUserInternal.addDefaultPrincipals = true
+#idp.authn.RemoteUserInternal.checkRemoteUser = true
+# Comma-delimited lists of attributes or headers to pull from
+#idp.authn.RemoteUserInternal.checkAttributes = 
+#idp.authn.RemoteUserInternal.checkHeaders = 
+# Simple transforms to apply
+#idp.authn.RemoteUserInternal.trim = true
+#idp.authn.RemoteUserInternal.lowercase = false
+#idp.authn.RemoteUserInternal.uppercase = false
+#idp.authn.RemoteUserInternal.matchExpression = 
+#idp.authn.RemoteUserInternal.allowedUsernames = 
+#idp.authn.RemoteUserInternal.deniedUsernames = 
+
+#### SPNEGO ####
+
+#idp.authn.SPNEGO.order = 1000
+#idp.authn.SPNEGO.nonBrowserSupported = false
+#idp.authn.SPNEGO.enforceRun = false
+#idp.authn.SPNEGO.refreshKrbConfig = false
+#idp.authn.SPNEGO.matchExpression = 
+idp.authn.SPNEGO.supportedPrincipals = \
+    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos, \
+    saml1/urn:ietf:rfc:1510
+
+#### X509 ####
+
+#idp.authn.X509.order = 1000
+#idp.authn.X509.nonBrowserSupported = false
+#idp.authn.X509.saveCertificateToCredentialSet = true
+# Servlet context-relative path to wherever your implementation lives
+#idp.authn.X509.externalAuthnPath = contextRelative:x509-prompt.jsp
+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, \
+    saml1/urn:ietf:rfc:2246
+
+#### X509Internal ####
+
+#idp.authn.X509Internal.order = 1000
+#idp.authn.X509Internal.nonBrowserSupported = false
+#idp.authn.X509Internal.saveCertificateToCredentialSet = true
+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, \
+    saml1/urn:ietf:rfc:2246
+
+#### IPAddress ####
+
+#idp.authn.IPAddress.order = 1000
+#idp.authn.IPAddress.passiveAuthenticationSupported = true
+#idp.authn.IPAddress.lifetime = PT60S
+#idp.authn.IPAddress.inactivityTimeout = PT60S
+idp.authn.IPAddress.supportedPrincipals = \
+   saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol
+
+#### Function ####
+
+#idp.authn.Function.order = 1000
+#idp.authn.Function.passiveAuthenticationSupported = true
+# Unset if you plan to return full Java Subject from function
+#idp.authn.Function.addDefaultPrincipals = true
+
+#### Duo ####
+
+#idp.authn.Duo.order = 1000
+#idp.authn.Duo.nonBrowserSupported = false
+#idp.authn.Duo.forcedAuthenticationSupported = true
+# Unset if you have advanced Duo integrations with individualized Principals
+#idp.authn.Duo.addDefaultPrincipals = true
+# The list below should be changed to reflect whatever locally- or
+# community-defined values are appropriate to represent Duo. It is
+# strongly advised that the value not be specific to Duo or any
+# particular technology to avoid lock-in.
+idp.authn.Duo.supportedPrincipals = \
+    saml2/http://example.org/ac/classes/mfa, \
+    saml1/http://example.org/ac/classes/mfa
+# Default Duo integration settings are defined separately
+# in duo.properties due to the sensitivity of the secret key.
+
+
+#### SAML ####
+
+#idp.authn.SAML.order = 1000
+#idp.authn.SAML.nonBrowserSupported = false
+#idp.authn.SAML.passiveAuthenticationSupported = true
+#idp.authn.SAML.forcedAuthenticationSupported = true
+#idp.authn.SAML.proxyScopingEnforced = true
+# Discovery options:
+#   Define shibboleth.authn.SAML.discoveryFunction bean
+#   Set proxyEntityID property
+#   Fall through to discovery via discoveryRequired property
+#idp.authn.SAML.proxyEntityID = https://idp.example.org/idp/shibboleth
+#idp.authn.SAML.discoveryRequired = true
+# 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.
+#idp.authn.SAML.addDefaultPrincipals = false
+#idp.authn.SAML.supportedPrincipals = \
+#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \
+#    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \
+#    saml1/urn:oasis:names:tc:SAML:1.0:am:password
+
+#### MFA ####
+
+#idp.authn.MFA.order = 1000
+#idp.authn.MFA.passiveAuthenticationSupported = true
+#idp.authn.MFA.forcedAuthenticationSupported = true
+#idp.authn.MFA.validateLoginTransitions = true
+# 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
+# combines IPAddress with Password.
+idp.authn.MFA.supportedPrincipals = \
+    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol, \
+    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \
+    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \
+    saml1/urn:oasis:names:tc:SAML:1.0:am:password
+# Most actual setup via mfa-authn-config.xml

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list