[java-identity-provider] branch main updated: IDP-1642 - Migrate configuration into jars where feasible

Scott Cantor cantor.2 at osu.edu
Tue Aug 25 18:52:32 UTC 2020


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=e45f02308bb46bed878f9a8580fd5246bba9b815

The following commit(s) were added to refs/heads/main by this push:
       new  e45f02308 IDP-1642 - Migrate configuration into jars where feasible
e45f02308 is described below

commit e45f02308bb46bed878f9a8580fd5246bba9b815
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Aug 25 14:52:23 2020 -0400

    IDP-1642 - Migrate configuration into jars where feasible
    
    https://issues.shibboleth.net/jira/browse/IDP-1642
    
    First stage of authn config redesign.
    Eliminate general-authn.xml and internalize descriptors.
    Add properties to control basic login characteristics.
---
 .../impl/AdministrativeFlowDescriptorManager.java  |   4 +-
 .../idp/authn/AuthenticationFlowDescriptor.java    |  88 ++++++-
 .../idp/authn/principal/PrincipalService.java      |  43 ++--
 .../authn/principal/PrincipalServiceManager.java   |  94 +++++++
 .../impl/AuthenticationFlowDescriptorManager.java  |   8 +-
 .../shibboleth/idp/conf/general-authn-system.xml   | 277 ++++++++++++++++++++-
 .../src/main/resources/conf/authn/authn.properties | 133 ++++++++++
 .../main/resources/conf/authn/general-authn.xml    | 173 -------------
 idp-conf/src/main/resources/conf/idp.properties    |   2 +-
 .../ProfileInterceptorFlowDescriptorManager.java   |   4 +-
 .../impl/AuthenticationMethodPrincipalService.java |  45 ++++
 .../impl/AuthnContextClassRefPrincipalService.java |  39 ++-
 .../impl/AuthnContextDeclRefPrincipalService.java  |  39 ++-
 13 files changed, 704 insertions(+), 245 deletions(-)

diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
index 6b4d771f4..9b5c348cc 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
@@ -28,7 +28,9 @@ import net.shibboleth.idp.admin.AdministrativeFlowDescriptor;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 
 /**
- * Manager of {@link AdministrativeFlowDescriptor} objects. 
+ * Manager of {@link AdministrativeFlowDescriptor} objects.
+ * 
+ *  @since 4.1.0
  */
 public class AdministrativeFlowDescriptorManager extends IdentifiedComponentManager<AdministrativeFlowDescriptor> {
 
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 238037951..83f202e70 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
@@ -34,6 +34,8 @@ import javax.annotation.Nullable;
 import javax.security.auth.Subject;
 
 import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.principal.PrincipalService;
+import net.shibboleth.idp.authn.principal.PrincipalServiceManager;
 import net.shibboleth.idp.authn.principal.PrincipalSupportingComponent;
 import net.shibboleth.idp.profile.FlowDescriptor;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
@@ -44,9 +46,11 @@ import net.shibboleth.utilities.java.support.component.ComponentInitializationEx
 import net.shibboleth.utilities.java.support.component.ComponentSupport;
 import net.shibboleth.utilities.java.support.logic.Constraint;
 import net.shibboleth.utilities.java.support.logic.PredicateSupport;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
 
 import org.opensaml.profile.context.ProfileRequestContext;
 import org.opensaml.storage.StorageSerializer;
+import org.springframework.core.Ordered;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicates;
@@ -62,7 +66,7 @@ import com.google.common.base.Predicates;
  */
 public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializableComponent implements
         FlowDescriptor, PrincipalSupportingComponent, Predicate<ProfileRequestContext>,
-            StorageSerializer<AuthenticationResult> {
+            StorageSerializer<AuthenticationResult>, Ordered {
 
     /** Prefix convention for flow IDs. */
     @Nonnull @NotEmpty public static final String FLOW_ID_PREFIX = "authn/";
@@ -70,6 +74,9 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
     /** Additional allowance for storage of result records to avoid race conditions during use. */
     @Nonnull public static final Duration STORAGE_EXPIRATION_OFFSET;
 
+    /** Spring auto-wiring order. */
+    private int order;
+    
     /** Whether this flow supports non-browser clients. */
     private boolean supportsNonBrowser;
     
@@ -97,6 +104,12 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
     /** Maximum amount of time since last usage that a flow should be considered active. */
     @Nonnull private Duration inactivityTimeout;
 
+    /**
+     * Supported principals provided by delimited strings, for post-initialization override via
+     * {@link PrincipalServiceManager}.
+     */
+    @Nonnull private Set<String> stringBasedPrincipals;
+
     /**
      * Supported principals, indexed by type, that the flow can produce. Implemented for the moment using the Subject
      * class for convenience to allow for class-based lookup in the {@link #getSupportedPrincipals} method.
@@ -111,9 +124,13 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
     
     /** Weighted sort oredering of custom Principals produced by flow(s). */
     @Nullable @NonnullElements private Map<Principal,Integer> principalWeightMap;
+    
+    /** Access to principal services. */
+    @Nullable private PrincipalServiceManager principalServiceManager;
 
     /** Constructor. */
     public AuthenticationFlowDescriptor() {
+        order = Ordered.LOWEST_PRECEDENCE;
         supportsNonBrowser = true;
         proxyRestrictionsEnforced = true;
         reuseCondition = new ProxyCountPredicate();
@@ -121,6 +138,21 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
         activationCondition = Predicates.alwaysTrue();
         inactivityTimeout = Duration.ofMinutes(30);
         principalWeightMap = Collections.emptyMap();
+        stringBasedPrincipals = Collections.emptySet();
+    }
+    
+    /** {@inheritDoc} */
+    public int getOrder() {
+        return order;
+    }
+    
+    /**
+     * Set the order/priority value for the bean.
+     * 
+     * @param priority priority value
+     */
+    public void setOrder(final int priority) {
+        order = priority;
     }
     
     /**
@@ -379,16 +411,33 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
     /**
      * Set supported non-user-specific principals that the flow may produce when it operates.
      * 
-     * @param <T> a type of principal to add, if not generic
      * @param principals supported principals to add
      */
-    public <T extends Principal> void setSupportedPrincipals(@Nonnull @NonnullElements final Collection<T> principals) {
+    public void setSupportedPrincipals(@Nonnull @NonnullElements final Collection<Principal> principals) {
         ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
         Constraint.isNotNull(principals, "Principal collection cannot be null.");
 
         supportedPrincipals.getPrincipals().clear();
         supportedPrincipals.getPrincipals().addAll(Set.copyOf(principals));
     }
+    
+    /**
+     * Set supported non-user-specific principals that the flow may produce when it operates.
+     * 
+     * <p>The principals must be prefixed by the ID of the relevant {@link PrincipalService} followed by a '/'.</p>
+     * 
+     * <p>Setting an empty list will leave any existing set unchanged. This is primarily provided to allow
+     * property-based override of an XML-based collection established with the previous method.</p>
+     * 
+     * @param principals supported principals to add
+     * 
+     * @since 4.1.0
+     */
+    public void setSupportedPrincipalsByString(@Nonnull @NonnullElements final Collection<String> principals) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+        stringBasedPrincipals = Set.copyOf(StringSupport.normalizeStringCollection(principals));
+    }
 
     /**
      * Set the activation condition in the form of a {@link Predicate} such that iff the condition evaluates to true
@@ -431,7 +480,20 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
         ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
         
         principalWeightMap = map != null ? map : Collections.emptyMap();
-    }    
+    }
+    
+    /**
+     * Sets a {@link PrincipalServiceManager} to use for string-based principal processing.
+     * 
+     * @param manager manager to set
+     * 
+     * @since 4.0.1
+     */
+    public void setPrincipalServiceManager(@Nullable final PrincipalServiceManager manager) {
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        principalServiceManager = manager;
+    }
 
     /** {@inheritDoc} */
     @Override protected void doInitialize() throws ComponentInitializationException {
@@ -440,6 +502,24 @@ public class AuthenticationFlowDescriptor extends AbstractIdentifiableInitializa
         if (resultSerializer == null) {
             throw new ComponentInitializationException("AuthenticationResult serializer cannot be null");
         }
+        
+        if (!stringBasedPrincipals.isEmpty()) {
+            if (principalServiceManager == null) {
+                throw new ComponentInitializationException("PrincipalServiceManager cannot be null");
+            }
+            
+            supportedPrincipals.getPrincipals().clear();
+            
+            stringBasedPrincipals.forEach(v -> {
+                final int index = v.indexOf('/');
+                if (index > 1 && index < v.length() - 1) {
+                    final PrincipalService<?> psvc = principalServiceManager.byId(v.substring(0, index));
+                    if (psvc != null) {
+                        supportedPrincipals.getPrincipals().add(psvc.newInstance(v.substring(index + 1)));
+                    }
+                }
+            });
+        }
     }
 
     /**
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalService.java
similarity index 55%
copy from idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
copy to idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalService.java
index 6b4d771f4..88e581681 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalService.java
@@ -15,32 +15,37 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.admin.impl;
+package net.shibboleth.idp.authn.principal;
 
-import java.util.Collection;
+import java.security.Principal;
 
-import javax.annotation.Nullable;
+import javax.annotation.Nonnull;
 
-import org.springframework.beans.factory.annotation.Autowired;
-
-import net.shibboleth.ext.spring.util.IdentifiedComponentManager;
-import net.shibboleth.idp.admin.AdministrativeFlowDescriptor;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
 
 /**
- * Manager of {@link AdministrativeFlowDescriptor} objects. 
+ * Interface that provides services for a {@link Principal} of a given type.
+ * 
+ * @param <T> principal type
+ * 
+ * @since 4.1.0
  */
-public class AdministrativeFlowDescriptorManager extends IdentifiedComponentManager<AdministrativeFlowDescriptor> {
+public interface PrincipalService<T extends Principal> extends IdentifiedComponent {
 
     /**
-     * Constructor.
-     *
-     * @param freeObjects  free-standing objects
+     * Get the type of object supported.
+     * 
+     * @return supported type
      */
-    @Autowired
-    public AdministrativeFlowDescriptorManager(
-            @Nullable @NonnullElements final Collection<AdministrativeFlowDescriptor> freeObjects) {
-        super(freeObjects);
-    }
-
+    @Nonnull Class<T> getType();
+    
+    /**
+     * Create a new instance of the appropriate type.
+     * 
+     * @param name principal name
+     * 
+     * @return new instance
+     */
+    @Nonnull T newInstance(@Nonnull @NotEmpty final String name);
 }
\ No newline at end of file
diff --git a/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalServiceManager.java b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalServiceManager.java
new file mode 100644
index 000000000..444c6fc9f
--- /dev/null
+++ b/idp-authn-api/src/main/java/net/shibboleth/idp/authn/principal/PrincipalServiceManager.java
@@ -0,0 +1,94 @@
+/*
+ * 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.principal;
+
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+/**
+ * Manages and exposes instances of the {@link PrincipalService} interface.
+ * 
+ * @since 4.1.0
+ */
+public class PrincipalServiceManager {
+    
+    /** Service index by class. */
+    @Nonnull @NonnullElements private final Map<Class<?>,PrincipalService<?>> classIndexedMap;
+
+    /** Service index by ID. */
+    @Nonnull @NonnullElements private final Map<String,PrincipalService<?>> idIndexedMap;
+
+    /**
+     * Constructor.
+     *
+     * @param services instances to manage
+     */
+    @Autowired
+    public PrincipalServiceManager(@Nullable @NonnullElements final Collection<PrincipalService<?>> services) {
+        if (services != null) {
+            classIndexedMap = new HashMap<>(services.size());
+            idIndexedMap = new HashMap<>(services.size());
+            services.forEach(ps -> {
+                classIndexedMap.put(ps.getType(), ps);
+                idIndexedMap.put(ps.getId(), ps);
+            });
+        } else {
+            classIndexedMap = Collections.emptyMap();
+            idIndexedMap = Collections.emptyMap();
+        }
+    }
+
+    /**
+     * Get a {@link PrincipalService} by type.
+     * 
+     * @param <T> class type
+     * @param claz class type
+     * 
+     * @return service for the type, or null
+     */
+    @Nullable public <T extends Principal> PrincipalService<T> byClass(@Nonnull final Class<T> claz) {
+        final PrincipalService<?> service = classIndexedMap.get(claz);
+        if (service != null) {
+            return service.getType().isAssignableFrom(claz) ? (PrincipalService<T>) service : null;
+        }
+        return null;
+    }
+    
+    /**
+     * Get a {@link PrincipalService} by ID.
+     * 
+     * @param id identifier
+     * 
+     * @return named service, or null
+     */
+    @Nullable public PrincipalService<?> byId(@Nonnull @NotEmpty final String id) {
+        return idIndexedMap.get(id);
+    }
+
+}
\ No newline at end of file
diff --git a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AuthenticationFlowDescriptorManager.java b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AuthenticationFlowDescriptorManager.java
index 74313bc92..b06eea2e6 100644
--- a/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AuthenticationFlowDescriptorManager.java
+++ b/idp-authn-impl/src/main/java/net/shibboleth/idp/authn/impl/AuthenticationFlowDescriptorManager.java
@@ -17,7 +17,7 @@
 
 package net.shibboleth.idp.authn.impl;
 
-import java.util.Collection;
+import java.util.List;
 
 import javax.annotation.Nullable;
 
@@ -28,7 +28,9 @@ import net.shibboleth.idp.authn.AuthenticationFlowDescriptor;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 
 /**
- * Manager of {@link AuthenticationFlowDescriptor} objects. 
+ * Manager of {@link AuthenticationFlowDescriptor} objects.
+ * 
+ * @since 4.1.0
  */
 public class AuthenticationFlowDescriptorManager extends IdentifiedComponentManager<AuthenticationFlowDescriptor> {
 
@@ -39,7 +41,7 @@ public class AuthenticationFlowDescriptorManager extends IdentifiedComponentMana
      */
     @Autowired
     public AuthenticationFlowDescriptorManager(
-            @Nullable @NonnullElements final Collection<AuthenticationFlowDescriptor> freeObjects) {
+            @Nullable @NonnullElements final List<AuthenticationFlowDescriptor> freeObjects) {
         super(freeObjects);
     }
 
diff --git a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/general-authn-system.xml b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/general-authn-system.xml
index 68f34c114..c0820c606 100644
--- a/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/general-authn-system.xml
+++ b/idp-conf-impl/src/main/resources/net/shibboleth/idp/conf/general-authn-system.xml
@@ -13,7 +13,7 @@
        default-destroy-method="destroy">
 
 	<import resource="${idp.home}/conf/authn/authn-comparison.xml" />
-	<import resource="${idp.home}/conf/authn/general-authn.xml" />
+	<import resource="conditional:${idp.home}/conf/authn/general-authn.xml" />
 
     <!-- Management bean to collect and expose AuthenticationFlowDescriptors. -->
     
@@ -21,17 +21,269 @@
         class="net.shibboleth.idp.authn.impl.AuthenticationFlowDescriptorManager"
         p:components="#{getObject('shibboleth.AvailableAuthenticationFlows')}" />
 
+    <!-- Defaulted flows. -->
+    
+    <bean p:id="authn/Password" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.Password.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.Password.nonBrowserSupported:true}"
+            p:passiveAuthenticationSupported="%{idp.authn.Password.passiveAuthenticationSupported:true}"
+            p:forcedAuthenticationSupported="%{idp.authn.Password.forcedAuthenticationSupported:true}"
+            p:proxyRestrictionsEnforced="%{idp.authn.Password.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.Password.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.Password.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.Password.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.Password.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+    
+    <bean p:id="authn/IPAddress" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.IPAddress.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.IPAddress.nonBrowserSupported:true}"
+            p:passiveAuthenticationSupported="%{idp.authn.IPAddress.passiveAuthenticationSupported:true}"
+            p:forcedAuthenticationSupported="%{idp.authn.IPAddress.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.IPAddress.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.IPAddress.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.IPAddress.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.IPAddress.lifetime:PT60S}"
+            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()}">
+        <property name="supportedPrincipals">
+            <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol" />
+        </property>
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.IPAddress.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean p:id="authn/Function" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.Function.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.Function.nonBrowserSupported:true}"
+            p:passiveAuthenticationSupported="%{idp.authn.Function.passiveAuthenticationSupported:true}"
+            p:forcedAuthenticationSupported="%{idp.authn.Function.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.Function.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.Function.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.Function.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.Function.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.Function.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean p:id="authn/External" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.External.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.External.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.External.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.External.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.External.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.External.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.External.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.External.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.External.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+        
+    <bean p:id="authn/RemoteUser" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.RemoteUser.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.RemoteUser.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.RemoteUser.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.RemoteUser.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.RemoteUser.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.RemoteUser.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.RemoteUser.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.RemoteUser.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.RemoteUser.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+    
+    <bean p:id="authn/RemoteUserInternal" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.RemoteUserInternal.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.RemoteUserInternal.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.RemoteUserInternal.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.RemoteUserInternal.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.RemoteUserInternal.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.RemoteUserInternal.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.RemoteUserInternal.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.RemoteUserInternal.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.RemoteUserInternal.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean p:id="authn/SAML" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.SAML.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.SAML.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.SAML.passiveAuthenticationSupported:true}"
+            p:forcedAuthenticationSupported="%{idp.authn.SAML.forcedAuthenticationSupported:true}"
+            p:proxyRestrictionsEnforced="%{idp.authn.SAML.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.SAML.proxyScopingEnforced:true}"
+            p:discoveryRequired="%{idp.authn.SAML.discoveryRequired:true}"
+            p:lifetime="%{idp.authn.SAML.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.SAML.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+            
+    <bean id="authn/SPNEGO" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.SPNEGO.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.SPNEGO.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.SPNEGO.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.SPNEGO.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.SPNEGO.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.SPNEGO.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.SPNEGO.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.SPNEGO.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipals">
+            <list>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos" />
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:method="urn:ietf:rfc:1510" />
+            </list>
+        </property>
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.SPNEGO.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean id="authn/X509" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.X509.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.X509.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.X509.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.X509.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.X509.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.X509.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.X509.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.X509.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipals">
+            <list>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:X509" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient" />
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:method="urn:ietf:rfc:2246" />
+            </list>
+        </property>
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.X509.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean id="authn/X509Internal" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.X509Internal.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.X509Internal.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.X509Internal.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.X509Internal.forcedAuthenticationSupported:false}"
+            p:proxyRestrictionsEnforced="%{idp.authn.X509Internal.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.X509Internal.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.X509Internal.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.X509Internal.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipals">
+            <list>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:X509" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient" />
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:method="urn:ietf:rfc:2246" />
+            </list>
+        </property>
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.X509Internal.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean id="authn/Duo" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.Duo.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.Duo.nonBrowserSupported:false}"
+            p:passiveAuthenticationSupported="%{idp.authn.Duo.passiveAuthenticationSupported:false}"
+            p:forcedAuthenticationSupported="%{idp.authn.Duo.forcedAuthenticationSupported:true}"
+            p:proxyRestrictionsEnforced="%{idp.authn.Duo.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.Duo.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.Duo.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.Duo.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            p:inactivityTimeout="%{idp.authn.Duo.inactivityTimeout:%{idp.authn.defaultTimeout:PT30M}}"
+            p:reuseCondition-ref="#{'%{idp.authn.Duo.reuseCondition:shibboleth.Conditions.TRUE}'.trim()}"
+            p:activationCondition-ref="#{'%{idp.authn.Duo.activationCondition:shibboleth.Conditions.TRUE}'.trim()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.Duo.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
+    <bean id="authn/MFA" parent="shibboleth.AuthenticationFlow"
+            p:order="%{idp.authn.MFA.order:1000}"
+            p:nonBrowserSupported="%{idp.authn.MFA.nonBrowserSupported:true}"
+            p:passiveAuthenticationSupported="%{idp.authn.MFA.passiveAuthenticationSupported:true}"
+            p:forcedAuthenticationSupported="%{idp.authn.MFA.forcedAuthenticationSupported:true}"
+            p:proxyRestrictionsEnforced="%{idp.authn.MFA.proxyRestrictionsEnforced:%{idp.authn.enforceProxyRestrictions:true}}"
+            p:proxyScopingEnforced="%{idp.authn.MFA.proxyScopingEnforced:false}"
+            p:discoveryRequired="%{idp.authn.MFA.discoveryRequired:false}"
+            p:lifetime="%{idp.authn.MFA.lifetime:%{idp.authn.defaultLifetime:PT1H}}"
+            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()}">
+        <property name="supportedPrincipalsByString">
+            <bean parent="shibboleth.CommaDelimStringArray"
+                c:_0="#{'%{idp.authn.MFA.supportedPrincipals:}'.trim()}" />
+        </property>
+    </bean>
+
     <!-- A parent bean to default some of the flow boilerplate. -->
 
     <bean id="shibboleth.AuthenticationFlow" abstract="true"
             class="net.shibboleth.idp.authn.AuthenticationFlowDescriptor"
             p:resultSerializer-ref="shibboleth.DefaultAuthenticationResultSerializer"
+            p:nonBrowserSupported="true"
             p:passiveAuthenticationSupported="false"
             p:forcedAuthenticationSupported="false"
-            p:nonBrowserSupported="true"
+            p:proxyRestrictionsEnforced="%{idp.authn.enforceProxyRestrictions:true}"
             p:lifetime="%{idp.authn.defaultLifetime:PT60M}"
             p:inactivityTimeout="%{idp.authn.defaultTimeout:PT30M}"
-            p:principalWeightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap')}">
+            p:principalWeightMap="#{getObject('shibboleth.AuthenticationPrincipalWeightMap') ?: getObject('shibboleth.DefaultAuthenticationPrincipalWeightMap')}"
+            p:principalServiceManager-ref="shibboleth.PrincipalServiceManager">
         <property name="supportedPrincipals">
             <list>
                 <bean parent="shibboleth.SAML2AuthnContextClassRef"
@@ -44,6 +296,25 @@
         </property>
     </bean>
 
+    <!-- Default weighting if not overridden. -->
+    <util:map id="shibboleth.DefaultAuthenticationPrincipalWeightMap">
+        <entry>
+            <key>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" />
+            </key>
+            <value>1</value>
+        </entry>
+    </util:map>
+
+    <!-- PrincipalServiceManager bean for auto-registration of various features. -->
+    <bean id="shibboleth.PrincipalServiceManager" class="net.shibboleth.idp.authn.principal.PrincipalServiceManager" />
+    
+    <!-- Default PrincipalService beans. -->
+    <bean p:id="saml1" class="net.shibboleth.idp.saml.authn.principal.impl.AuthenticationMethodPrincipalService" />
+    <bean p:id="saml2classref" class="net.shibboleth.idp.saml.authn.principal.impl.AuthnContextClassRefPrincipalService" />
+    <bean p:id="saml2declref" class="net.shibboleth.idp.saml.authn.principal.impl.AuthnContextDeclRefPrincipalService" />
+
     <!-- Default list of custom Principal serializers; users can define their own list and merge it with this one. -->
     <bean id="shibboleth.DefaultPrincipalSerializers"
             class="org.springframework.beans.factory.config.ListFactoryBean">
diff --git a/idp-conf/src/main/resources/conf/authn/authn.properties b/idp-conf/src/main/resources/conf/authn/authn.properties
new file mode 100644
index 000000000..bb821a6e1
--- /dev/null
+++ b/idp-conf/src/main/resources/conf/authn/authn.properties
@@ -0,0 +1,133 @@
+# 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
+
+# Properties below override specific method behavior, as an alternative
+# to defining Spring beans in XML. Refer to the documentation for a complete
+# list. Most 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
+# 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
+
+#### External ####
+
+#idp.authn.External.order = 1000
+#idp.authn.External.nonBrowserSupported = false
+
+#### RemoteUser ####
+
+#idp.authn.RemoteUser.order = 1000
+#idp.authn.RemoteUser.nonBrowserSupported = false
+
+#### RemoteUserInternal ####
+
+#idp.authn.RemoteUserInternal.order = 1000
+#idp.authn.RemoteUserInternal.nonBrowserSupported = false
+
+#### SPNEGO ####
+
+#idp.authn.SPNEGO.order = 1000
+#idp.authn.SPNEGO.nonBrowserSupported = false
+#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.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.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
+
+#### Duo ####
+
+#idp.authn.Duo.order = 1000
+#idp.authn.Duo.nonBrowserSupported = false
+#idp.authn.Duo.forcedAuthenticationSupported = 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
+
+#### 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
+#idp.authn.SAML.discoveryRequired = true
+
+#### MFA ####
+
+#idp.authn.MFA.order = 1000
+#idp.authn.MFA.passiveAuthenticationSupported = true
+#idp.authn.MFA.forcedAuthenticationSupported = 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
diff --git a/idp-conf/src/main/resources/conf/authn/general-authn.xml b/idp-conf/src/main/resources/conf/authn/general-authn.xml
deleted file mode 100644
index b936f9782..000000000
--- a/idp-conf/src/main/resources/conf/authn/general-authn.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:context="http://www.springframework.org/schema/context"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xmlns:p="http://www.springframework.org/schema/p"
-       xmlns:c="http://www.springframework.org/schema/c"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
-                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
-                           
-       default-init-method="initialize"
-       default-destroy-method="destroy">
-
-    <!--
-    This file provisions the IdP with information about the configured login mechanisms available for use.
-    The actual beans and subflows that make up those mechanisms are in their own files, but this pulls them
-    together with deployer-supplied metadata to describe them to the system.
-    
-    You can turn on and off individual mechanisms by adding and remove them here. Nothing left out will
-    be used, regardless any other files loaded by the Spring container.
-    
-    Flow defaults include: no support for IsPassive/ForceAuthn, support for non-browser clients enabled,
-    and default timeout and lifetime values set via properties. We also default to supporting the SAML 1/2
-    expressions for password-based authentication over a secure channel, so anything more exotic requires
-    customization, as the examples below for IP address and SPNEGO authentication illustrate.
-    -->
-
-    <util:list id="shibboleth.AvailableAuthenticationFlows">
-        
-        <bean id="authn/IPAddress" parent="shibboleth.AuthenticationFlow"
-                p:passiveAuthenticationSupported="true"
-                p:lifetime="PT60S" p:inactivityTimeout="PT60S">
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol" />
-                </list>
-            </property>
-        </bean>
-
-        <bean id="authn/SPNEGO" parent="shibboleth.AuthenticationFlow"
-                p:nonBrowserSupported="false">
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos" />
-                    <bean parent="shibboleth.SAML1AuthenticationMethod"
-                        c:method="urn:ietf:rfc:1510" />
-                </list>
-            </property>
-        </bean>
-        
-        <bean id="authn/Function" parent="shibboleth.AuthenticationFlow" />
-
-        <bean id="authn/X509" parent="shibboleth.AuthenticationFlow"
-                p:nonBrowserSupported="false">
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:X509" />
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient" />
-                    <bean parent="shibboleth.SAML1AuthenticationMethod"
-                        c:method="urn:ietf:rfc:2246" />
-                </list>
-            </property>
-        </bean>
-
-        <bean id="authn/X509Internal" parent="shibboleth.AuthenticationFlow">
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:X509" />
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient" />
-                    <bean parent="shibboleth.SAML1AuthenticationMethod"
-                        c:method="urn:ietf:rfc:2246" />
-                </list>
-            </property>
-        </bean>
-
-        <bean id="authn/Password" parent="shibboleth.AuthenticationFlow"
-                p:passiveAuthenticationSupported="true"
-                p:forcedAuthenticationSupported="true" />
-
-        <bean id="authn/Duo" parent="shibboleth.AuthenticationFlow"
-                p:forcedAuthenticationSupported="true"
-                p:nonBrowserSupported="false">
-            <!--
-            The list below should be changed to reflect whatever locally- or
-            community-defined values are appropriate to represent MFA. It is
-            strongly advised that the value not be specific to Duo or any
-            particular technology.
-            -->
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="http://example.org/ac/classes/mfa" />
-                    <bean parent="shibboleth.SAML1AuthenticationMethod"
-                        c:method="http://example.org/ac/classes/mfa" />
-                </list>
-            </property>
-        </bean>
-
-        <bean id="authn/MFA" parent="shibboleth.AuthenticationFlow"
-                p:passiveAuthenticationSupported="true"
-                p:forcedAuthenticationSupported="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.
-            -->
-            <property name="supportedPrincipals">
-                <list>
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol" />
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" />
-                    <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                        c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Password" />
-                    <bean parent="shibboleth.SAML1AuthenticationMethod"
-                        c:method="urn:oasis:names:tc:SAML:1.0:am:password" />
-                </list>
-            </property>
-        </bean>
-
-        <!-- This is a flow for proxied SAML authentication to another IdP. -->
-
-        <bean id="authn/SAML" parent="shibboleth.AuthenticationFlow"
-            p:nonBrowserSupported="false"
-            p:passiveAuthenticationSupported="true"
-            p:forcedAuthenticationSupported="true"
-            p:proxyScopingEnforced="true"
-            p:discoveryRequired="true" />
-
-        <!--
-        These flows are often, though not exclusively, used to proxy authentication, so may need
-        the proxyScopingEnforced flag enabled by hand to honor RP/local proxy count limits,
-        and may optionally trigger discovery via the discoveryRequired flag.
-        -->
-
-        <bean id="authn/External" parent="shibboleth.AuthenticationFlow"
-            p:nonBrowserSupported="false" />
-
-        <bean id="authn/RemoteUser" parent="shibboleth.AuthenticationFlow"
-            p:nonBrowserSupported="false" />
-
-        <bean id="authn/RemoteUserInternal" parent="shibboleth.AuthenticationFlow" />
-
-    </util:list>
-
-    <!--
-    This is a map used to "weight" particular methods above others if the IdP has to randomly select one
-    to insert into a SAML authentication statement. The typical use shown below is to bias the IdP in favor
-    of expressing the SAML 2 PasswordProtectedTransport class over the more vanilla Password class on the
-    assumption that the IdP doesn't accept passwords via an insecure channel. This map never causes the IdP
-    to violate its matching rules if an RP requests a particular value; it only matters when nothing specific
-    is chosen. Anything not in the map has a weight of zero.
-    -->
-    
-    <util:map id="shibboleth.AuthenticationPrincipalWeightMap">
-        <entry>
-            <key>
-                <bean parent="shibboleth.SAML2AuthnContextClassRef"
-                    c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" />
-            </key>
-            <value>1</value>
-        </entry>
-    </util:map>
-
-</beans>
diff --git a/idp-conf/src/main/resources/conf/idp.properties b/idp-conf/src/main/resources/conf/idp.properties
index 76e3ff7fc..29ecb51bb 100644
--- a/idp-conf/src/main/resources/conf/idp.properties
+++ b/idp-conf/src/main/resources/conf/idp.properties
@@ -1,5 +1,5 @@
 # Load any additional property resources from a comma-delimited list
-idp.additionalProperties = /conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/admin/admin.properties, /conf/authn/duo.properties, /credentials/secrets.properties
+idp.additionalProperties = /conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/admin/admin.properties, /conf/authn/authn.properties, /conf/authn/duo.properties, /credentials/secrets.properties
 
 # In most cases (and unless noted in the surrounding comments) the
 # commented settings in the distributed files document default behavior.
diff --git a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ProfileInterceptorFlowDescriptorManager.java b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ProfileInterceptorFlowDescriptorManager.java
index c7e3403d8..b1552fc9f 100644
--- a/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ProfileInterceptorFlowDescriptorManager.java
+++ b/idp-profile-impl/src/main/java/net/shibboleth/idp/profile/interceptor/impl/ProfileInterceptorFlowDescriptorManager.java
@@ -28,7 +28,9 @@ import net.shibboleth.idp.profile.interceptor.ProfileInterceptorFlowDescriptor;
 import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
 
 /**
- * Manager of {@link ProfileInterceptorFlowDescriptor} objects. 
+ * Manager of {@link ProfileInterceptorFlowDescriptor} objects.
+ * 
+ * @since 4.1.0
  */
 public class ProfileInterceptorFlowDescriptorManager
         extends IdentifiedComponentManager<ProfileInterceptorFlowDescriptor> {
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthenticationMethodPrincipalService.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthenticationMethodPrincipalService.java
new file mode 100644
index 000000000..ba6175047
--- /dev/null
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthenticationMethodPrincipalService.java
@@ -0,0 +1,45 @@
+/*
+ * 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.saml.authn.principal.impl;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.idp.authn.principal.PrincipalService;
+import net.shibboleth.idp.saml.authn.principal.AuthenticationMethodPrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
+
+/**
+ * {@link PrincipalService} for {@link AuthenticationMethodPrincipal}.
+ * 
+ * @since 4.1.0
+ */
+public class AuthenticationMethodPrincipalService extends AbstractIdentifiableInitializableComponent
+        implements PrincipalService<AuthenticationMethodPrincipal> {
+
+    /** {@inheritDoc} */
+    @Nonnull public Class<AuthenticationMethodPrincipal> getType() {
+        return AuthenticationMethodPrincipal.class;
+    }
+    
+    /** {@inheritDoc} */
+    public AuthenticationMethodPrincipal newInstance(@Nonnull @NotEmpty final String name) {
+        return new AuthenticationMethodPrincipal(name);
+    }
+
+}
\ No newline at end of file
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextClassRefPrincipalService.java
similarity index 50%
copy from idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
copy to idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextClassRefPrincipalService.java
index 6b4d771f4..c29939151 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextClassRefPrincipalService.java
@@ -15,32 +15,31 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.admin.impl;
+package net.shibboleth.idp.saml.authn.principal.impl;
 
-import java.util.Collection;
+import javax.annotation.Nonnull;
 
-import javax.annotation.Nullable;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import net.shibboleth.ext.spring.util.IdentifiedComponentManager;
-import net.shibboleth.idp.admin.AdministrativeFlowDescriptor;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.idp.authn.principal.PrincipalService;
+import net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
 
 /**
- * Manager of {@link AdministrativeFlowDescriptor} objects. 
+ * {@link PrincipalService} for {@link AuthnContextClassRefPrincipal}.
+ * 
+ * @since 4.1.0
  */
-public class AdministrativeFlowDescriptorManager extends IdentifiedComponentManager<AdministrativeFlowDescriptor> {
+public class AuthnContextClassRefPrincipalService extends AbstractIdentifiableInitializableComponent
+        implements PrincipalService<AuthnContextClassRefPrincipal> {
+
+    /** {@inheritDoc} */
+    @Nonnull public Class<AuthnContextClassRefPrincipal> getType() {
+        return AuthnContextClassRefPrincipal.class;
+    }
 
-    /**
-     * Constructor.
-     *
-     * @param freeObjects  free-standing objects
-     */
-    @Autowired
-    public AdministrativeFlowDescriptorManager(
-            @Nullable @NonnullElements final Collection<AdministrativeFlowDescriptor> freeObjects) {
-        super(freeObjects);
+    /** {@inheritDoc} */
+    public AuthnContextClassRefPrincipal newInstance(@Nonnull @NotEmpty final String name) {
+        return new AuthnContextClassRefPrincipal(name);
     }
 
 }
\ No newline at end of file
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextDeclRefPrincipalService.java
similarity index 50%
copy from idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
copy to idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextDeclRefPrincipalService.java
index 6b4d771f4..562506832 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/AdministrativeFlowDescriptorManager.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/authn/principal/impl/AuthnContextDeclRefPrincipalService.java
@@ -15,32 +15,31 @@
  * limitations under the License.
  */
 
-package net.shibboleth.idp.admin.impl;
+package net.shibboleth.idp.saml.authn.principal.impl;
 
-import java.util.Collection;
+import javax.annotation.Nonnull;
 
-import javax.annotation.Nullable;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import net.shibboleth.ext.spring.util.IdentifiedComponentManager;
-import net.shibboleth.idp.admin.AdministrativeFlowDescriptor;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.idp.authn.principal.PrincipalService;
+import net.shibboleth.idp.saml.authn.principal.AuthnContextDeclRefPrincipal;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
 
 /**
- * Manager of {@link AdministrativeFlowDescriptor} objects. 
+ * {@link PrincipalService} for {@link AuthnContextDeclRefPrincipal}.
+ * 
+ * @since 4.1.0
  */
-public class AdministrativeFlowDescriptorManager extends IdentifiedComponentManager<AdministrativeFlowDescriptor> {
+public class AuthnContextDeclRefPrincipalService extends AbstractIdentifiableInitializableComponent
+        implements PrincipalService<AuthnContextDeclRefPrincipal> {
+
+    /** {@inheritDoc} */
+    @Nonnull public Class<AuthnContextDeclRefPrincipal> getType() {
+        return AuthnContextDeclRefPrincipal.class;
+    }
 
-    /**
-     * Constructor.
-     *
-     * @param freeObjects  free-standing objects
-     */
-    @Autowired
-    public AdministrativeFlowDescriptorManager(
-            @Nullable @NonnullElements final Collection<AdministrativeFlowDescriptor> freeObjects) {
-        super(freeObjects);
+    /** {@inheritDoc} */
+    public AuthnContextDeclRefPrincipal newInstance(@Nonnull @NotEmpty final String name) {
+        return new AuthnContextDeclRefPrincipal(name);
     }
 
 }
\ No newline at end of file

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


More information about the commits mailing list