diff --git a/README.md b/README.md
index 8fe42b3..dc2e6bd 100644
--- a/README.md
+++ b/README.md
@@ -14,3 +14,4 @@ to complete a deployment.
     * Internal Testing - (TEST) branch/repo that uses the "test bed" which is something that I2 provides (LDAP) and an element to make all integrations.  Appropriate for Jenkins and testing environments
   * `release` branch
     * External Testing - (RELEASE) branch/repo (ultimately will live in Subversion?) for end users
+
diff --git a/conf/access-control.xml b/conf/access-control.xml
index a9184e6..3853722 100644
--- a/conf/access-control.xml
+++ b/conf/access-control.xml
@@ -34,7 +34,7 @@
         </entry>
         
         <!--
-        <entry key="AccessByUser">
+        <entry key="AccessByAdminUser">
             <bean parent="shibboleth.PredicateAccessControl">
                 <constructor-arg>
                     <bean parent="shibboleth.Conditions.SubjectName" c:collection="#{'jdoe'}" />
diff --git a/conf/admin/admin.properties b/conf/admin/admin.properties
new file mode 100644
index 0000000..7f14b56
--- /dev/null
+++ b/conf/admin/admin.properties
@@ -0,0 +1,55 @@
+# Configure properties controlling administrative features
+
+#idp.status.logging = Status
+#idp.status.accessPolicy = AccessByIPAddress
+#idp.status.authenticated = false
+#idp.status.nonBrowserSupported = false
+#idp.status.resolveAttributes = false
+
+#idp.reload.logging = Reload
+#idp.reload.accessPolicy = AccessByIPAddress
+#idp.reload.authenticated = false
+#idp.reload.nonBrowserSupported = false
+#idp.reload.resolveAttributes = false
+
+#idp.resolvertest.logging = ResolverTest
+#idp.resolvertest.accessPolicy = AccessByIPAddress
+#idp.resolvertest.authenticated = false
+#idp.resolvertest.nonBrowserSupported = false
+#idp.resolvertest.resolveAttributes = false
+
+#idp.mdquery.logging = MetadataQuery
+#idp.mdquery.accessPolicy = AccessByIPAddress
+#idp.mdquery.authenticated = false
+#idp.mdquery.nonBrowserSupported = false
+#idp.mdquery.resolveAttributes = false
+
+#idp.metrics.logging = Metrics
+#idp.metrics.authenticated = false
+#idp.metrics.nonBrowserSupported = false
+#idp.metrics.resolveAttributes = false
+# See admin/metrics.xml for other configuration
+
+#idp.hello.logging = Hello
+#idp.hello.accessPolicy = AccessByAdminUser
+#idp.hello.authenticated = true
+#idp.hello.nonBrowserSupported = false
+#idp.hello.resolveAttributes = true
+
+#idp.lockout.logging = Lockout
+#idp.lockout.accessPolicy = AccessDenied
+#idp.lockout.authenticated = false
+#idp.lockout.nonBrowserSupported = false
+#idp.lockout.resolveAttributes = false
+
+#idp.storage.logging = Storage
+#idp.storage.accessPolicy = AccessDenied
+#idp.storage.authenticated = false
+#idp.storage.nonBrowserSupported = false
+#idp.storage.resolveAttributes = false
+
+#idp.unlock-keys.logging = UnlockKeys
+#idp.unlock-keys.accessPolicy = AccessDenied
+#idp.unlock-keys.authenticated = true
+#idp.unlock-keys.nonBrowserSupported = false
+#idp.unlock-keys.resolveAttributes = false
diff --git a/conf/admin/general-admin.xml b/conf/admin/general-admin.xml
deleted file mode 100644
index 2814bf6..0000000
--- a/conf/admin/general-admin.xml
+++ /dev/null
@@ -1,74 +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">
-
-    <util:list id="shibboleth.AvailableAdminFlows">
-    
-        <!-- Status Page -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/status"
-            p:loggingId="%{idp.service.logging.status:Status}"
-            p:policyName="%{idp.status.accessPolicy:AccessByIPAddress}" />
-
-        <!-- Service Reload -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/reload-service-configuration"
-            p:loggingId="%{idp.service.logging.serviceReload:Reload}"
-            p:policyName="%{idp.reload.accessPolicy:AccessByIPAddress}" />
-
-        <!-- MetadataResolver Reload -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/reload-metadata"
-            p:loggingId="%{idp.service.logging.serviceReload:Reload}"
-            p:policyName="%{idp.reload.accessPolicy:AccessByIPAddress}" />
-
-        <!-- AttributeResolver Debugging -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/resolvertest"
-            p:loggingId="%{idp.service.logging.resolvertest:ResolverTest}"
-            p:policyName="%{idp.resolvertest.accessPolicy:AccessByIPAddress}" />
-
-        <!-- Metadata Query -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/mdquery"
-            p:loggingId="MetadataQuery"
-            p:policyName="AccessByIPAddress" />
-
-        <!-- REST AccountLockoutManager Access -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/lockout-manager"
-            p:loggingId="Lockout"
-            p:policyName="AccessByIPAddress" />
-
-        <!-- REST StorageService Access -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/storage"
-            p:loggingId="Storage"
-            p:policyName="AccessByIPAddress" />
-    
-        <!-- REST Interface to Metrics -->
-        <bean parent="shibboleth.AdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/metrics"
-            p:loggingId="Metrics"
-            p:policyNameLookupStrategy-ref="shibboleth.metrics.AccessPolicyStrategy" />
-
-        <!-- Attended Startup Unlock -->
-        <!--
-        <bean parent="shibboleth.OneTimeAdminFlow"
-            c:id="http://shibboleth.net/ns/profiles/unlock-keys"
-            p:loggingId="UnlockKeys"
-            p:authenticated="true"
-            p:policyName="AccessByAdminUser" />
-        -->
-    
-    </util:list>
-
-</beans>
diff --git a/conf/admin/metrics.xml b/conf/admin/metrics.xml
index f9b5c16..208ab6b 100644
--- a/conf/admin/metrics.xml
+++ b/conf/admin/metrics.xml
@@ -26,8 +26,11 @@
                 <ref bean="shibboleth.metrics.MetadataGaugeSet" />
                 <ref bean="shibboleth.metrics.NameIdentifierGaugeSet" />
                 <ref bean="shibboleth.metrics.RelyingPartyGaugeSet" />
+                <ref bean="shibboleth.metrics.AttributeRegistryGaugeSet" />
                 <ref bean="shibboleth.metrics.AttributeResolverGaugeSet" />
                 <ref bean="shibboleth.metrics.AttributeFilterGaugeSet" />
+                <ref bean="shibboleth.metrics.CASServiceRegistryGaugeSet" />
+                <ref bean="shibboleth.metrics.ManagedBeanGaugeSet" />
 
                 <!--
                 <bean class="com.codahale.metrics.jvm.CachedThreadStatesGaugeSet"
@@ -57,10 +60,20 @@
         <entry key="metadata" value-ref="shibboleth.metrics.MetadataGaugeSet" />
         <entry key="nameid" value-ref="shibboleth.metrics.NameIdentifierGaugeSet" />
         <entry key="relyingparty" value-ref="shibboleth.metrics.RelyingPartyGaugeSet" />
+        <entry key="registry" value-ref="shibboleth.metrics.AttributeRegistryGaugeSet" />
         <entry key="resolver" value-ref="shibboleth.metrics.AttributeResolverGaugeSet" />
         <entry key="filter" value-ref="shibboleth.metrics.AttributeFilterGaugeSet" />
+        <entry key="cas" value-ref="shibboleth.metrics.CASServiceRegistryGaugeSet" />
+        <entry key="bean" value-ref="shibboleth.metrics.ManagedBeanGaugeSet" />
     </util:map>
-        
+
+    <!-- Add any desired properties into set to expose them as IdP metrics. -->
+    <!--
+    <util:set id="shibboleth.metrics.ExposedProperties">
+        <value>idp.entityID</value>
+    </util:set>
+    -->
+    
     <!-- If you don't specify an alternate access policy, this named policy will be enforced. -->
     <bean id="shibboleth.metrics.DefaultAccessPolicy" class="java.lang.String" c:_0="AccessByIPAddress" />
     
diff --git a/conf/intercept/impersonate-intercept-config.xml b/conf/attribute-registry.xml
similarity index 63%
rename from conf/intercept/impersonate-intercept-config.xml
rename to conf/attribute-registry.xml
index 7dfda2b..133930b 100644
--- a/conf/intercept/impersonate-intercept-config.xml
+++ b/conf/attribute-registry.xml
@@ -13,13 +13,17 @@
        default-destroy-method="destroy">
 
     <!--
-    Names of access control policies defined in access-control.xml to control impersonation.
-    The general policy runs first and determines whether to offer the impersonation option.
-    The specific policy runs second and determines whether to allow the requested impersonation.
+    The system comes preconfigured to load rules directly from resource files
+    configured in services.xml so they're monitored for changes.
+    
+    You can add mappings here, add more XML resource files, or drop property
+    files into the directory noted below, but they won't be monitored for changes
+    themselves.
     -->
 
-    <bean id="shibboleth.impersonate.GeneralPolicy" class="java.lang.String" c:_0="GeneralImpersonationPolicy" />
-
-    <bean id="shibboleth.impersonate.SpecificPolicy" class="java.lang.String" c:_0="SpecificImpersonationPolicy" />
-    
+    <!-- Default directory for custom mappings. -->
+    <bean parent="shibboleth.TranscodingRuleLoader"
+        c:dir="%{idp.home}/conf/attributes/custom"
+        c:extensions="#{{'.txt', '.props', '.properties', '.rule'}}" />
+   
 </beans>
diff --git a/conf/attribute-resolver-full.xml b/conf/attribute-resolver-full.xml
deleted file mode 100644
index e44ffbc..0000000
--- a/conf/attribute-resolver-full.xml
+++ /dev/null
@@ -1,319 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    This file is an EXAMPLE configuration file containing lots of commented
-    example attributes, encoders, and a couple of example data connectors.
-     
-    Not all attribute definitions or data connectors are demonstrated, but
-    a variety of LDAP attributes, some common to Shibboleth deployments and
-    many not, are included.
-    
-    Deployers should refer to the Identity Provider 3 documentation
-    
-    https://wiki.shibboleth.net/confluence/display/IDP30/AttributeResolverConfiguration
-     
-    for a complete list of components and their options.
--->
-<AttributeResolver
-        xmlns="urn:mace:shibboleth:2.0:resolver"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
-
-    <!-- ========================================== -->
-    <!--      Attribute Definitions                 -->
-    <!-- ========================================== -->
-
-    <!-- Schema: Core schema attributes-->
-<!--
-
-    <AttributeDefinition xsi:type="Simple" id="uid">
-        <InputDataConnector ref="myLDAP" attributeNames="uid"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.1" friendlyName="uid" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="mail">
-        <InputDataConnector ref="myLDAP" attributeNames="mail"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="homePhone">
-        <InputDataConnector ref="myLDAP" attributeNames="homePhone"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:homePhone" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.20" friendlyName="homePhone" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="homePostalAddress">
-        <InputDataConnector ref="myLDAP" attributeNames="homePostalAddress"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:homePostalAddress" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.39" friendlyName="homePostalAddress" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="mobileNumber">
-        <InputDataConnector ref="myLDAP" attributeNames="mobile"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mobile" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.41" friendlyName="mobile" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="pagerNumber">
-        <InputDataConnector ref="myLDAP" attributeNames="pager"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:pager" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.42" friendlyName="pager" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="surname">
-        <InputDataConnector ref="myLDAP" attributeNames="sn"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:sn" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.4" friendlyName="sn" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="locality">
-        <InputDataConnector ref="myLDAP" attributeNames="l"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:l" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.7" friendlyName="l" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="stateProvince">
-        <InputDataConnector ref="myLDAP" attributeNames="st"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:st" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.8" friendlyName="st" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="street">
-        <InputDataConnector ref="myLDAP" attributeNames="street"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:street" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.9" friendlyName="street" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="organizationName">
-        <InputDataConnector ref="myLDAP" attributeNames="o"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:o" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.10" friendlyName="o" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="organizationalUnit">
-        <InputDataConnector ref="myLDAP" attributeNames="ou"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:ou" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.11" friendlyName="ou" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="title">
-        <InputDataConnector ref="myLDAP" attributeNames="title"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:title" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.12" friendlyName="title" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="postalAddress">
-        <InputDataConnector ref="myLDAP" attributeNames="postalAddress"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:postalAddress" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.16" friendlyName="postalAddress" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="postalCode">
-        <InputDataConnector ref="myLDAP" attributeNames="postalCode"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:postalCode" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.17" friendlyName="postalCode" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="postOfficeBox">
-        <InputDataConnector ref="myLDAP" attributeNames="postOfficeBox"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:postOfficeBox" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.18" friendlyName="postOfficeBox" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="telephoneNumber">
-        <InputDataConnector ref="myLDAP" attributeNames="telephoneNumber"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:telephoneNumber" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.20" friendlyName="telephoneNumber" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="givenName">
-        <InputDataConnector ref="myLDAP" attributeNames="givenName"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:givenName" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.42" friendlyName="givenName" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="initials">
-        <InputDataConnector ref="myLDAP" attributeNames="initials"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:initials" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.5.4.43" friendlyName="initials" encodeType="false" />
-    </AttributeDefinition>
--->
-
-    <!-- Schema: inetOrgPerson attributes-->
-<!--
-    <AttributeDefinition xsi:type="Simple" id="departmentNumber">
-        <InputDataConnector ref="myLDAP" attributeNames="departmentNumber"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:departmentNumber" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.2" friendlyName="departmentNumber" encodeType="false" />
-    </AttributeDefinition>
-    
-    <AttributeDefinition xsi:type="Simple" id="displayName">
-        <InputDataConnector ref="myLDAP" attributeNames="displayName"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:displayName" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.241" friendlyName="displayName" encodeType="false" />
-    </AttributeDefinition> 
-
-    <AttributeDefinition xsi:type="Simple" id="employeeNumber">
-        <InputDataConnector ref="myLDAP" attributeNames="employeeNumber"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:employeeNumber" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.3" friendlyName="employeeNumber" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="employeeType">
-        <InputDataConnector ref="myLDAP" attributeNames="employeeType"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:employeeType" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.4" friendlyName="employeeType" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="jpegPhoto">
-        <InputDataConnector ref="myLDAP" attributeNames="jpegPhoto"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:jpegPhoto" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.60" friendlyName="jpegPhoto" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="preferredLanguage">
-        <InputDataConnector ref="myLDAP" attributeNames="preferredLanguage"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:preferredLanguage" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:2.16.840.1.113730.3.1.39" friendlyName="preferredLanguage" encodeType="false" />
-    </AttributeDefinition>
--->
-    <!-- Schema: eduPerson attributes -->
-<!-- 
-    <AttributeDefinition xsi:type="Simple" id="eduPersonAffiliation">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation" />
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAffiliation" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" friendlyName="eduPersonAffiliation" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="eduPersonEntitlement">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonEntitlement"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonEntitlement" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" friendlyName="eduPersonEntitlement" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="eduPersonNickname">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonNickname"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonNickname" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.2" friendlyName="eduPersonNickname" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Simple" id="eduPersonPrimaryAffiliation">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrimaryAffiliation"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.5" friendlyName="eduPersonPrimaryAffiliation" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Prescoped" id="eduPersonPrincipalName">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalName"/>
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Prescoped" id="eduPersonPrincipalNamePrior">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalNamePrior"/>
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.12" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.12" friendlyName="eduPersonPrincipalNamePrior" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation" encodeType="false" />
-    </AttributeDefinition>
-    
-    <AttributeDefinition xsi:type="Simple" id="eduPersonAssurance">
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonAssurance"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonAssurance" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" friendlyName="eduPersonAssurance" encodeType="false" />
-    </AttributeDefinition>
--->
-
-    <!-- Semi-deprecated eduPersonUniqueId, should be phased out in favor of SAML subject-id replacement below. -->
-<!-- 
-    <AttributeDefinition xsi:type="Scoped" id="eduPersonUniqueId" scope="%{idp.scope}">
-        <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}"/>
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.13" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.13" friendlyName="eduPersonUniqueId" encodeType="false" />
-    </AttributeDefinition>
--->
-
-    <!-- Schema: SAML Subject ID Attributes -->
-<!--
-    <AttributeDefinition xsi:type="Scoped" id="samlSubjectID" scope="%{idp.scope}">
-        <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}"/>
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oasis:names:tc:SAML:attribute:subject-id" friendlyName="subject-id" encodeType="false" />
-    </AttributeDefinition>
-
-    <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
-        <InputDataConnector ref="computed" attributeNames="computedId"/>
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oasis:names:tc:SAML:attribute:pairwise-id" friendlyName="pairwise-id" encodeType="false" />
-    </AttributeDefinition>
--->
-
-    <!-- ========================================== -->
-    <!--      Data Connectors                       -->
-    <!-- ========================================== -->
-
-    <!-- Example Static Connector -->
-
-    <!-- Example Relational Database Connector -->
-<!--
-    <DataConnector id="mySIS" xsi:type="RelationalDatabase">
-        <ApplicationManagedConnection jdbcDriver="oracle.jdbc.driver.OracleDriver"
-                                         jdbcURL="jdbc:oracle:thin:@db.example.org:1521:SomeDB" 
-                                         jdbcUserName="myid" 
-                                         jdbcPassword="mypassword" />
-        <QueryTemplate>
-            <![CDATA[
-                SELECT * FROM student WHERE gzbtpid = '$resolutionContext.principal'
-            ]]>
-        </QueryTemplate>
-
-        <Column columnName="gzbtpid" attributeID="uid" />
-        <Column columnName="fqlft" attributeID="gpa" />
-    </DataConnector>
--->
-
-    <!-- Example LDAP Connector -->
-<!--
-    <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
-        ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
-        baseDN="%{idp.attribute.resolver.LDAP.baseDN}" 
-        principal="%{idp.attribute.resolver.LDAP.bindDN}"
-        principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
-        useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
-        connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
-		trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
-        responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}">
-        <FilterTemplate>
-            <![CDATA[
-                %{idp.attribute.resolver.LDAP.searchFilter}
-            ]]>
-        </FilterTemplate>
-	    <ConnectionPool
-            minPoolSize="%{idp.pool.LDAP.minSize:3}"
-            maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
-            blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
-            validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
-            validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
-            expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"
-            failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
-    </DataConnector>
--->
-
-    <!-- DataConector for pairwise-id (example depends on saml-nameid.properties). -->
-
-<!-- 
-    <DataConnector id="computed" xsi:type="ComputedId"
-	    generatedAttributeID="computedId"
-	    salt="%{idp.persistentId.salt}"
-	    algorithm="%{idp.persistentId.algorithm:SHA}"
-        encoding="%{idp.persistentId.encoding:BASE32}">
-	    
-        <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
-        
-	</DataConnector>
--->
-
-</AttributeResolver>
diff --git a/conf/attribute-resolver-ldap.xml b/conf/attribute-resolver-ldap.xml
deleted file mode 100644
index 69154c0..0000000
--- a/conf/attribute-resolver-ldap.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-    This file is an EXAMPLE configuration file. While the configuration
-    presented in this example file is semi-functional, it isn't very
-    interesting. It is here only as a starting point for your deployment
-    process.
-    
-    Very few attribute definitions and data connectors are demonstrated,
-    and use of LDAP is assumed, with the LDAP configuration primarily
-    supplied from the ldap.properties file.
-
-    Attribute-resolver-full.xml contains more examples of attributes,
-    encoders, and data connectors. Deployers should refer to the Shibboleth
-    documentation for a complete list of components and their options.
--->
-<AttributeResolver
-        xmlns="urn:mace:shibboleth:2.0:resolver"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
-        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
-
-    <!-- ========================================== -->
-    <!--      Attribute Definitions                 -->
-    <!-- ========================================== -->
-
-    <!--
-    The EPPN is the "standard" federated username in higher ed.
-    For guidelines on the implementation of this attribute, refer
-    to the Shibboleth and eduPerson documentation. Above all, do
-    not expose a value for this attribute without considering the
-    long term implications. 
-    -->
-    <AttributeDefinition id="eduPersonPrincipalName" xsi:type="Prescoped" >
-        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalName"/>
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" />
-    </AttributeDefinition>
-
-    <!--
-    The uid is the closest thing to a "standard" LDAP attribute
-    representing a local username, but you should generally *never*
-    expose uid to federated services, as it is rarely globally unique.
-    -->
-    <AttributeDefinition id="uid" xsi:type="Simple" >
-        <InputDataConnector ref="myLDAP" attributeNames="uid"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.1" friendlyName="uid" encodeType="false" />
-    </AttributeDefinition>
-
-    <!--
-    In the rest of the world, the email address is the standard identifier,
-    despite the problems with that practice. Consider making the EPPN value
-    the same as your official email addresses whenever possible.
-    -->
-    <AttributeDefinition id="mail" xsi:type="Simple" >
-        <InputDataConnector ref="myLDAP" attributeNames="mail"/>
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false" />
-    </AttributeDefinition>
-        
-    <!-- ========================================== -->
-    <!--      Data Connectors                       -->
-    <!-- ========================================== -->
-    
-    <!--
-    Example LDAP Connector
-    
-    The connectivity details can be specified in ldap.properties to
-    share them with your authentication settings if desired.
-    -->
-    <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
-        ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
-        baseDN="%{idp.attribute.resolver.LDAP.baseDN}" 
-        principal="%{idp.attribute.resolver.LDAP.bindDN}"
-        principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
-        useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
-        connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
-        trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
-        responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}">
-        <FilterTemplate>
-            <![CDATA[
-                %{idp.attribute.resolver.LDAP.searchFilter}
-            ]]>
-        </FilterTemplate>
-	    <ConnectionPool
-            minPoolSize="%{idp.pool.LDAP.minSize:3}"
-            maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
-            blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
-            validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
-            validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
-            expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"
-            failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
-    </DataConnector>
-
-</AttributeResolver>
diff --git a/conf/attribute-resolver.xml b/conf/attribute-resolver.xml
index 471bf0b..8d16a59 100644
--- a/conf/attribute-resolver.xml
+++ b/conf/attribute-resolver.xml
@@ -1,17 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 
-    This file is an EXAMPLE configuration file. While the configuration
-    presented in this example file is semi-functional, it isn't very
-    interesting. It is here only as a starting point for your deployment
-    process.
-    
-    Very few attribute definitions and data connectors are demonstrated,
-    and the data is derived statically from the logged-in username and a
-    static example connector.
+This file is a rudimentary example. While it is semi-functional, it isn't very
+interesting. It is here only as a starting point for your deployment process
+to avoid any dependency on components like an LDAP directory.
 
-    Attribute-resolver-full.xml contains more examples of attributes,
-    encoders, and data connectors. Deployers should refer to the Shibboleth
-    documentation for a complete list of components and their options.
+Very few attribute definitions and data connectors are demonstrated, and the
+data is derived statically from the logged-in username and a static example
+connector.
+
+The file(s) in the examples directory contain more examples that involve more
+complex approaches. Deployers should refer to the documentation for a complete
+list of possible components and their options.
 -->
 <AttributeResolver
         xmlns="urn:mace:shibboleth:2.0:resolver" 
@@ -32,8 +31,6 @@
     -->
     <AttributeDefinition id="eduPersonPrincipalName" xsi:type="Scoped" scope="%{idp.scope}">
         <InputAttributeDefinition ref="uid" />
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" />
     </AttributeDefinition>
 
     <!--
@@ -41,10 +38,7 @@
     representing a local username, but you should generally *never*
     expose uid to federated services, as it is rarely globally unique.
     -->
-    <AttributeDefinition id="uid" xsi:type="PrincipalName">
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.1" friendlyName="uid" encodeType="false" />
-    </AttributeDefinition>
+    <AttributeDefinition id="uid" xsi:type="PrincipalName" />
 
     <!--
     In the rest of the world, the email address is the standard identifier,
@@ -53,14 +47,11 @@
     -->
     <AttributeDefinition id="mail" xsi:type="Template">
         <InputAttributeDefinition ref="uid" />
-        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:mail" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" encodeType="false" />
         <Template>
           <![CDATA[
                ${uid}@example.org
           ]]>
         </Template>
-        <SourceAttribute>uid</SourceAttribute>
     </AttributeDefinition>
 
     <!--
@@ -68,8 +59,6 @@
     -->
     <AttributeDefinition id="eduPersonScopedAffiliation" xsi:type="Scoped" scope="%{idp.scope}">
         <InputDataConnector ref="staticAttributes" attributeNames="affiliation" />
-        <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" encodeType="false" />
-        <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation" encodeType="false" />
     </AttributeDefinition>
 
 
diff --git a/conf/attributes/custom/README b/conf/attributes/custom/README
new file mode 100644
index 0000000..98977b0
--- /dev/null
+++ b/conf/attributes/custom/README
@@ -0,0 +1,9 @@
+# You can create custom attribute mapping rules using
+# simple property files stored in this directory tree.
+# Spring property replacement is NOT supported.
+
+# As an example, a default SAML 2 rule for eduPersonPrincipalName would be:
+
+#id=eduPersonPrincipalName
+#transcoder=SAML2ScopedStringTranscoder
+#saml2.name=urn:oid:1.3.6.1.4.1.5923.1.1.1.6
diff --git a/conf/authn/x509-internal-authn-config.xml b/conf/attributes/default-rules.xml
similarity index 67%
rename from conf/authn/x509-internal-authn-config.xml
rename to conf/attributes/default-rules.xml
index bad3029..c865157 100644
--- a/conf/authn/x509-internal-authn-config.xml
+++ b/conf/attributes/default-rules.xml
@@ -12,10 +12,17 @@
        default-init-method="initialize"
        default-destroy-method="destroy">
 
+    <!-- Default Attribute transcoding rules. -->
+    
     <!--
-    You can define a TrustEngine to apply to any candidate certificates by defining a bean named
-    "shibboleth.authn.X509.TrustEngine". You could also define that in conf/global.xml if you need
-    to share one between the internal and external versions of this flow.
+    Many if not most of these attributes are not suited or may even be actively discouraged
+    from use in federated protocols, but this is merely a set of well-known definitions, not
+    a recommended set to support or use.
     -->
     
+    <import resource="inetOrgPerson.xml" />
+    <import resource="eduPerson.xml" />
+    <import resource="eduCourse.xml" />
+    <import resource="samlSubject.xml" />
+
 </beans>
diff --git a/conf/attributes/eduCourse.xml b/conf/attributes/eduCourse.xml
new file mode 100644
index 0000000..6794da6
--- /dev/null
+++ b/conf/attributes/eduCourse.xml
@@ -0,0 +1,50 @@
+<?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">
+
+    <bean parent="shibboleth.TranscodingRuleLoader">
+    <constructor-arg>
+    <list>
+        
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduCourseOffering</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.6.1.1</prop>
+                    <prop key="saml1.name">urn:oid:1.3.6.1.4.1.5923.1.6.1.1</prop>
+                    <prop key="displayName.en">Course offering</prop>
+                    <prop key="description.en">Unique identifier for a course offering</prop>
+                </props>
+            </property>
+        </bean>
+        
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduCourseMember</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder SAML1ScopedStringTranscoder CASScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.6.1.2</prop>
+                    <prop key="saml1.name">urn:oid:1.3.6.1.4.1.5923.1.6.1.2</prop>
+                    <prop key="saml1.encodeType">false</prop>
+                    <prop key="displayName.en">Course role</prop>
+                    <prop key="description.en">Specifies the person's role within a particular course offering</prop>
+                </props>
+            </property>
+        </bean>
+
+    </list>
+    </constructor-arg>
+    </bean>
+    
+</beans>
diff --git a/conf/attributes/eduPerson.xml b/conf/attributes/eduPerson.xml
new file mode 100644
index 0000000..afe1299
--- /dev/null
+++ b/conf/attributes/eduPerson.xml
@@ -0,0 +1,266 @@
+<?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">
+       
+    <bean parent="shibboleth.TranscodingRuleLoader">
+    <constructor-arg>
+    <list>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonAffiliation</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.1</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonAffiliation</prop>
+                    <prop key="displayName.en">Affiliation</prop>
+                    <prop key="displayName.de">Zugehörigkeit</prop>
+                    <prop key="displayName.fr">Affiliation</prop>
+                    <prop key="displayName.it">Tipo di membro</prop>
+                    <prop key="displayName.ja">職位</prop>
+                    <prop key="description.en">Affiliation: Type of affiliation with Home Organization</prop>
+                    <prop key="description.de">Art der Zugehörigkeit zur Heimatorganisation</prop>
+                    <prop key="description.de-ch">Art der Zugehörigkeit zur Heimorganisation</prop>
+                    <prop key="description.fr">Type d'affiliation dans l'organisation</prop>
+                    <prop key="description.it">Tipo di membro: Tipo di lavoro svolto per l'organizzazione</prop>
+                    <prop key="description.ja">所属機関における職位(faculty,staff,student,memberなど)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonAssurance</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.11</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonAssurance</prop>
+                    <prop key="displayName.en">Assurance level</prop>
+                    <prop key="displayName.de">Vertrauensgrad</prop>
+                    <prop key="displayName.fr">Niveau de confiance</prop>
+                    <prop key="displayName.it">Livello di sicurezza</prop>
+                    <prop key="displayName.ja">保証レベル</prop>
+                    <prop key="description.en">Set of URIs that assert compliance with specific standards for identity assurance.</prop>
+                    <prop key="description.de">URIs die eine gewisse Zusicherung für spezifische Standards des Vertrauens beinhalten</prop>
+                    <prop key="description.fr">Un ensemble d'URI qui attestent la conformité selon un standard pour les niveaux d'assurance d'identités</prop>
+                    <prop key="description.it">Un insieme di URI che asseriscono l'osservanza dei livelli di sicurezza richiesti</prop>
+                    <prop key="description.ja">IDの保証レベルに関して特定の基準に準拠していることを示すURI</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonEntitlement</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.7</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonEntitlement</prop>
+                    <prop key="displayName.en">Entitlement</prop>
+                    <prop key="displayName.de">Berechtigung</prop>
+                    <prop key="displayName.fr">Entitlement</prop>
+                    <prop key="displayName.it">Prerogativa</prop>
+                    <prop key="displayName.ja">資格情報</prop>
+                    <prop key="description.en">Member of: URI (either URL or URN) that indicates a set of rights to specific resources based on an agreement across the releavant community</prop>
+                    <prop key="description.de">Zeichenkette, die Rechte für spezifische Ressourcen beschreibt</prop>
+                    <prop key="description.fr">Membre de: URI (soit une URL ou une URN) décrivant un droit spécific d'accès.</prop>
+                    <prop key="description.it">Membro delle seguenti URI (sia URL o URN) che rappresentano diritti specifici d'accesso validi in tutta la communità</prop>
+                    <prop key="description.ja">特定のアプリケーションもしくはコミュニティ内の複数リソースへのアクセス権限を持つことを示すURI(URLもしくはURN)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonNickname</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.2</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonNickname</prop>
+                    <prop key="displayName.en">Nickname</prop>
+                    <prop key="displayName.de">Kurzname</prop>
+                    <prop key="displayName.de-ch">Übername</prop>
+                    <prop key="displayName.fr">Surnom</prop>
+                    <prop key="displayName.it">Diminutivo</prop>
+                    <prop key="displayName.ja">ニックネーム</prop>
+                    <prop key="description.en">Person's nickname, or the informal name by which they are accustomed to be hailed.</prop>
+                    <prop key="description.de">Kurzname einer Person, oder üblicher Rufname zur Begrüßung.</prop>
+                    <prop key="description.de-ch">Übername einer Person, oder üblicher Rufname zur Begrüssung.</prop>
+                    <prop key="description.fr">Nom personnalisable pour un usage informel.</prop>
+                    <prop key="description.it">Diminutivo della persona, o  soprannome.</prop>
+                    <prop key="description.ja">利用者のニックネームもしくは通称</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonOrgDN</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.3</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonOrgDN</prop>
+                    <prop key="displayName.en">Organization distinguished name</prop>
+                    <prop key="description.en">Distinguished name (DN) of the directory entry representing the institution with which the person is associated.</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonOrgUnitDN</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.4</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonOrgUnitDN</prop>
+                    <prop key="displayName.en">Organization unit distinguished name</prop>
+                    <prop key="description.en">Distinguished name(s) (DN) of the directory entries representing the person's Organizational Unit(s).</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonOrcid</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.16</prop>
+                    <prop key="saml1.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.16</prop>
+                    <prop key="displayName.en">ORCID</prop>
+                    <prop key="description.en">ORCID researcher identifier(s) belonging to a person.</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonPrimaryAffiliation</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.5</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation</prop>
+                    <prop key="displayName.en">Primary affiliation</prop>
+                    <prop key="displayName.de">Primäre Zugehörigkeit</prop>
+                    <prop key="displayName.fr">Affiliation pricipale</prop>
+                    <prop key="displayName.it">Appartenenza principale</prop>
+                    <prop key="displayName.ja">主要職位</prop>
+                    <prop key="description.en">Specifies the person's primary relationship to the institution in broad categories such as student, faculty, staff, alum, etc.</prop>
+                    <prop key="description.de">Spezifiziert der Hauptbeziehung einer Person innerhalb ihrer Organisation in groben Kategorien wie Student, Mitarbeiter, Alumni, etc.</prop>
+                    <prop key="description.fr">Spécifie la relation principale d'une personne avec l'institution selon des majeures catégories comme étudiant, collaborateur, alumni etc.</prop>
+                    <prop key="description.it">Specifica la relazione principale dell persona con l'istituzione secondo le maggiori categorie come studente, collaboratore, alumni, etc.</prop>
+                    <prop key="description.ja">所属機関における主要な職位(faculty,staff,student,memberなど)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonPrimaryOrgUnitDN</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.8</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonPrimaryOrgUnitDN</prop>
+                    <prop key="displayName.en">Primary organization unit distinguished name</prop>
+                    <prop key="description.en">Distinguished name (DN) of the directory entry representing the person's primary Organizational Unit.</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonPrincipalName</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder SAML1ScopedStringTranscoder CASScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.6</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonPrincipalName</prop>
+                    <prop key="saml1.encodeType">false</prop>
+                    <prop key="displayName.en">Principal name</prop>
+                    <prop key="displayName.de">Persönliche ID</prop>
+                    <prop key="displayName.fr">Principal Name</prop>
+                    <prop key="displayName.it">Principal Name</prop>
+                    <prop key="displayName.ja">プリンシパルID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly for inter-institutional user identification.</prop>
+                    <prop key="description.de">Eindeutige Benutzeridentifikation</prop>
+                    <prop key="description.de-ch">Eindeutige Benützeridentifikation</prop>
+                    <prop key="description.fr">L'identifiant unique de l'utilisateur</prop>
+                    <prop key="description.it">Un ID personale che identifica chiaramente l'utente in seno alla sua organizzazione</prop>
+                    <prop key="description.ja">フェデレーション内で一意かつ永続的な利用者識別子</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonPrincipalNamePrior</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder SAML1ScopedStringTranscoder CASScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.12</prop>
+                    <prop key="saml1.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.12</prop>
+                    <prop key="saml1.encodeType">false</prop>
+                    <prop key="displayName.en">Prior principal name(s)</prop>
+                    <prop key="description.en">eduPersonPrincipalName value(s) previously associated with the entry.</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonScopedAffiliation</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder SAML1ScopedStringTranscoder CASScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.9</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:eduPersonScopedAffiliation</prop>
+                    <prop key="saml1.encodeType">false</prop>
+                    <prop key="displayName.en">Scoped affiliation</prop>
+                    <prop key="displayName.de">Zugehörigkeit</prop>
+                    <prop key="displayName.fr">Affiliation</prop>
+                    <prop key="displayName.it">Tipo di membro</prop>
+                    <prop key="displayName.ja">スコープ付き職位</prop>
+                    <prop key="description.en">Specifies the person's affiliation within a particular security domain</prop>
+                    <prop key="description.de">Art der Zugehörigkeit zur Heimatorganisation</prop>
+                    <prop key="description.de-ch">Art der Zugehörigkeit zur Heimorganisation</prop>
+                    <prop key="description.fr">Type d'affiliation dans l'organisation</prop>
+                    <prop key="description.it">Tipo di membro: Tipo di lavoro svolto per l'organizzazione</prop>
+                    <prop key="description.ja">セキュリティドメインのスコープが付いた所属機関における職位</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">eduPersonUniqueId</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder SAML1ScopedStringTranscoder CASScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.13</prop>
+                    <prop key="saml1.name">urn:oid:1.3.6.1.4.1.5923.1.1.1.13</prop>
+                    <prop key="saml1.encodeType">false</prop>
+                    <prop key="displayName.en">Unique ID</prop>
+                    <prop key="displayName.de">Eindeutige ID</prop>
+                    <prop key="displayName.fr">ID unique</prop>
+                    <prop key="displayName.it">ID unico</prop>
+                    <prop key="displayName.ja">ユニークID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly for inter-institutional user identification.</prop>
+                    <prop key="description.de">Eindeutige Benutzeridentifikation</prop>
+                    <prop key="description.de-ch">Eindeutige Benützeridentifikation</prop>
+                    <prop key="description.fr">Identifiant unique de l'utilisateur</prop>
+                    <prop key="description.it">Un identificativo personale che identifica chiaramente l'utente in seno alla sua organizzazione</prop>
+                    <prop key="description.ja">フェデレーション内で一意で永続的かつ難読化された利用者識別子(後継はサブジェクトID)</prop>
+                </props>
+            </property>
+        </bean>
+
+    </list>
+    </constructor-arg>
+    </bean>
+    
+</beans>
diff --git a/conf/attributes/inetOrgPerson.xml b/conf/attributes/inetOrgPerson.xml
new file mode 100644
index 0000000..f2aebb1
--- /dev/null
+++ b/conf/attributes/inetOrgPerson.xml
@@ -0,0 +1,510 @@
+<?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">
+
+    <!-- https://tools.ietf.org/html/rfc2798 -->
+
+    <bean parent="shibboleth.TranscodingRuleLoader">
+    <constructor-arg>
+    <list>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">cn</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.3</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:cn</prop>
+                    <prop key="displayName.en">Common name</prop>
+                    <prop key="description.en">Common name of a person</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">departmentNumber</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.16.840.1.113730.3.1.2</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:departmentNumber</prop>
+                    <prop key="displayName.en">Department number</prop>
+                    <prop key="displayName.de">Abteilungsnummer</prop>
+                    <prop key="description.en">Department number</prop>
+                    <prop key="description.de">Nummer der Abteilung</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">displayName</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.16.840.1.113730.3.1.241</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:displayName</prop>
+                    <prop key="displayName.en">Display name</prop>
+                    <prop key="displayName.de">Anzeigename</prop>
+                    <prop key="displayName.fr">Nom</prop>
+                    <prop key="displayName.it">Nome</prop>
+                    <prop key="displayName.ja">表示名</prop>
+                    <prop key="description.en">The name that should appear in white-pages-like applications for this person.</prop>
+                    <prop key="description.de">Anzeigename</prop>
+                    <prop key="description.fr">Nom complet d'affichage</prop>
+                    <prop key="description.it">Nome</prop>
+                    <prop key="description.ja">アプリケーションでの表示に用いられる英字氏名</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">employeeNumber</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.16.840.1.113730.3.1.3</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:employeeNumber</prop>
+                    <prop key="displayName.en">Employee number</prop>
+                    <prop key="displayName.de">Mitarbeiternummer</prop>
+                    <prop key="displayName.fr">Numéro d'employé</prop>
+                    <prop key="displayName.it">Numero dell'utente</prop>
+                    <prop key="displayName.ja">従業員番号</prop>
+                    <prop key="description.en">Identifies an employee within an organization</prop>
+                    <prop key="description.de">Identifiziert einen Mitarbeiter innerhalb der Organisation</prop>
+                    <prop key="description.fr">Identifie un employé au sein de l'organisation</prop>
+                    <prop key="description.it">Identifica l' utente presso l'organizzazione</prop>
+                    <prop key="description.ja">所属機関における利用者の従業員番号</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">employeeType</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.16.840.1.113730.3.1.4</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:employeeType</prop>
+                    <prop key="displayName.en">Employee type</prop>
+                    <prop key="description.en">Employee type</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">givenName</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.42</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:givenName</prop>
+                    <prop key="displayName.en">Given name</prop>
+                    <prop key="displayName.de">Vorname</prop>
+                    <prop key="displayName.fr">Prénom</prop>
+                    <prop key="displayName.it">Nome</prop>
+                    <prop key="displayName.ja">名</prop>
+                    <prop key="description.en">Given name of a person</prop>
+                    <prop key="description.de">Vorname</prop>
+                    <prop key="description.fr">Prénom de l'utilisateur</prop>
+                    <prop key="description.it">Nome</prop>
+                    <prop key="description.ja">氏名(名)の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">homePhone</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.20</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:homePhone</prop>
+                    <prop key="displayName.en">Private phone number</prop>
+                    <prop key="displayName.de">Telefon Privat</prop>
+                    <prop key="displayName.fr">Teléphone personnel</prop>
+                    <prop key="displayName.it">Numero di telefono privato</prop>
+                    <prop key="displayName.ja">自宅電話番号</prop>
+                    <prop key="description.en">Private phone number</prop>
+                    <prop key="description.de">Private Telefonnummer</prop>
+                    <prop key="description.fr">Numéro de téléphone de domicile de la personne</prop>
+                    <prop key="description.it">Numero di telefono privato</prop>
+                    <prop key="description.ja">自宅の電話番号</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">homePostalAddress</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.39</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:homePostalAddress</prop>
+                    <prop key="displayName.en">Home postal address</prop>
+                    <prop key="displayName.de">Heimatadresse</prop>
+                    <prop key="displayName.de-ch">Heimadresse</prop>
+                    <prop key="displayName.fr">Adresse personnelle</prop>
+                    <prop key="displayName.it">Indirizzo personale</prop>
+                    <prop key="displayName.ja">自宅住所</prop>
+                    <prop key="description.en">Home postal address: Home address of the user</prop>
+                    <prop key="description.de">Heimatadresse</prop>
+                    <prop key="description.de-ch">Heimadresse</prop>
+                    <prop key="description.fr">Adresse postale de domicile de la personne</prop>
+                    <prop key="description.it">Indirizzo personale: indirizzo dove abita l'utente</prop>
+                    <prop key="description.ja">自宅の住所</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">initials</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.43</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:initials</prop>
+                    <prop key="displayName.en">Initials</prop>
+                    <prop key="displayName.de">Initialen</prop>
+                    <prop key="displayName.fr">Initiales</prop>
+                    <prop key="displayName.ja">イニシャル</prop>
+                    <prop key="description.en">Initials</prop>
+                    <prop key="description.de">Anfangsbuchstaben des Namens</prop>
+                    <prop key="description.de-ch">Die Anfangsbuchstaben</prop>
+                    <prop key="description.fr">L' initiales</prop>
+                    <prop key="description.ja">イニシャル</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">l</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.7</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:l</prop>
+                    <prop key="displayName.en">Locality name</prop>
+                    <prop key="displayName.de">Ort</prop>
+                    <prop key="displayName.fr">Locality name</prop>
+                    <prop key="displayName.ja">場所(L)</prop>
+                    <prop key="description.en">Locality name</prop>
+                    <prop key="description.de">Ort</prop>
+                    <prop key="description.fr">Nom de la localité où réside l'objet</prop>
+                    <prop key="description.ja">場所の名前 日本の場合は市区町村名</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">mail</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.3</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:mail</prop>
+                    <prop key="displayName.en">E-mail</prop>
+                    <prop key="displayName.de">E-Mail</prop>
+                    <prop key="displayName.fr">Email</prop>
+                    <prop key="displayName.it">E-mail</prop>
+                    <prop key="displayName.ja">メールアドレス</prop>
+                    <prop key="description.en">E-Mail: Preferred address for e-mail to be sent to this person</prop>
+                    <prop key="description.de">E-Mail-Adresse</prop>
+                    <prop key="description.de-ch">E-Mail Adresse</prop>
+                    <prop key="description.fr">Adresse de courrier électronique</prop>
+                    <prop key="description.it">E-Mail: l'indirizzo e-mail preferito dall'utente</prop>
+                    <prop key="description.ja">メールアドレス</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">mobile</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.41</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:mobile</prop>
+                    <prop key="displayName.en">Mobile phone number</prop>
+                    <prop key="displayName.de">Telefon Mobil</prop>
+                    <prop key="displayName.fr">Numéro de mobile</prop>
+                    <prop key="displayName.it">Numero di cellulare</prop>
+                    <prop key="displayName.ja">携帯電話番号</prop>
+                    <prop key="description.en">Mobile phone number</prop>
+                    <prop key="description.de">Mobile Telefonnummer</prop>
+                    <prop key="description.fr">Numéro de teléphone mobile</prop>
+                    <prop key="description.it">Numero di cellulare</prop>
+                    <prop key="description.ja">携帯電話の電話番号</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">o</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.10</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:o</prop>
+                    <prop key="displayName.en">Organization name</prop>
+                    <prop key="displayName.de">Organisationsname</prop>
+                    <prop key="displayName.fr">Nom de l'organisation</prop>
+                    <prop key="displayName.ja">所属機関名</prop>
+                    <prop key="description.en">Organization name</prop>
+                    <prop key="description.de">Name der Organisation</prop>
+                    <prop key="description.fr">Nom de l'organisation</prop>
+                    <prop key="description.ja">所属機関名称の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">ou</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.11</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:ou</prop>
+                    <prop key="displayName.en">Organizational unit</prop>
+                    <prop key="displayName.de">Organisationseinheit</prop>
+                    <prop key="displayName.fr">Unité organisationnelle</prop>
+                    <prop key="displayName.ja">機関内所属名</prop>
+                    <prop key="description.en">Organizational unit</prop>
+                    <prop key="description.de">Name der Organisationseinheit</prop>
+                    <prop key="description.fr">Nom de l'unité organisationnelle</prop>
+                    <prop key="description.ja">機関内所属名称の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">pager</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.42</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:pager</prop>
+                    <prop key="displayName.en">Pager number</prop>
+                    <prop key="description.en">Pager number</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">postalAddress</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.16</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:postalAddress</prop>
+                    <prop key="displayName.en">Business postal address</prop>
+                    <prop key="displayName.de">Geschäftsadresse</prop>
+                    <prop key="displayName.fr">Adresse professionnelle</prop>
+                    <prop key="displayName.it">Indirizzo professionale</prop>
+                    <prop key="displayName.ja">所属機関住所</prop>
+                    <prop key="description.en">Business postal address: Campus or office address</prop>
+                    <prop key="description.de">Geschäftliche Adresse</prop>
+                    <prop key="description.de-ch">Adresse am Arbeitsplatz</prop>
+                    <prop key="description.fr">Adresse de l'institut, de l'université</prop>
+                    <prop key="description.it">Indirizzo professionale: indirizzo dell'istituto o dell'ufficio</prop>
+                    <prop key="description.ja">所属機関の住所</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">postalCode</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.17</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:postalCode</prop>
+                    <prop key="displayName.en">Postal code</prop>
+                    <prop key="displayName.en-us">ZIP code</prop>
+                    <prop key="displayName.de">Postleitzahl</prop>
+                    <prop key="displayName.fr">Code postal</prop>
+                    <prop key="displayName.ja">郵便番号</prop>
+                    <prop key="description.en">Postal code</prop>
+                    <prop key="description.en-us">ZIP code</prop>
+                    <prop key="description.de">Postleitzahl</prop>
+                    <prop key="description.fr">Code postal</prop>
+                    <prop key="description.ja">郵便番号</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">postOfficeBox</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:mace:dir:attribute-def:postOfficeBox</prop>
+                    <prop key="saml1.name">urn:oid:2.5.4.18</prop>
+                    <prop key="displayName.en">Postal box</prop>
+                    <prop key="displayName.de">Postfach</prop>
+                    <prop key="displayName.fr">Boite postale</prop>
+                    <prop key="displayName.fr-ch">Case postale</prop>
+                    <prop key="displayName.ja">私書箱</prop>
+                    <prop key="description.en">Postal box identifier</prop>
+                    <prop key="description.de">Postfach</prop>
+                    <prop key="description.fr">Boite postale</prop>
+                    <prop key="description.fr-ch">Case postale</prop>
+                    <prop key="description.ja">私書箱</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">preferredLanguage</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.16.840.1.113730.3.1.39</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:preferredLanguage</prop>
+                    <prop key="displayName.en">Preferred Language</prop>
+                    <prop key="displayName.de">Bevorzugte Sprache</prop>
+                    <prop key="displayName.fr">Langue préférée</prop>
+                    <prop key="displayName.it">Lingua preferita</prop>
+                    <prop key="displayName.ja">希望言語</prop>
+                    <prop key="description.en">Preferred language: Users preferred language (see RFC1766)</prop>
+                    <prop key="description.de">Bevorzugte Sprache (siehe RFC1766)</prop>
+                    <prop key="description.fr">Exemple: fr, de, it, en, ... (voir RFC1766)</prop>
+                    <prop key="description.it">Lingua preferita: la lingua preferita dall'utente (cfr. RFC1766)</prop>
+                    <prop key="description.ja">利用者が希望する言語(RFC1766 を参照)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">sn</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.4</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:sn</prop>
+                    <prop key="displayName.en">Surname</prop>
+                    <prop key="displayName.de">Nachname</prop>
+                    <prop key="displayName.fr">Nom de famille</prop>
+                    <prop key="displayName.it">Cognome</prop>
+                    <prop key="displayName.ja">姓</prop>
+                    <prop key="description.en">Surname or family name</prop>
+                    <prop key="description.de">Familienname</prop>
+                    <prop key="description.fr">Nom de famille de l'utilisateur.</prop>
+                    <prop key="description.it">Cognome dell'utilizzatore</prop>
+                    <prop key="description.ja">氏名(姓)の英語表記</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">st</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.8</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:st</prop>
+                    <prop key="displayName.en">State or province name</prop>
+                    <prop key="displayName.ja">都道府県もしくは州や省(ST)</prop>
+                    <prop key="description.en">State or province name</prop>
+                    <prop key="description.ja">州名や省名 国によって異なり日本の場合は都道府県名</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">street</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.9</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:street</prop>
+                    <prop key="displayName.en">Street</prop>
+                    <prop key="displayName.de">Straße</prop>
+                    <prop key="displayName.de-ch">Strasse</prop>
+                    <prop key="displayName.fr">Rue</prop>
+                    <prop key="displayName.ja">通り</prop>
+                    <prop key="description.en">Street address</prop>
+                    <prop key="description.de">Name der Straße</prop>
+                    <prop key="description.de-ch">Strassenadresse</prop>
+                    <prop key="description.fr">Nom de rue</prop>
+                    <prop key="description.ja">通りおよび番地</prop>
+                </props>
+            </property>
+        </bean>
+
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">telephoneNumber</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.20</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:telephoneNumber</prop>
+                    <prop key="displayName.en">Business phone number</prop>
+                    <prop key="displayName.de">Telefon Geschäft</prop>
+                    <prop key="displayName.fr">Teléphone professionnel</prop>
+                    <prop key="displayName.it">Numero di telefono dell'ufficio</prop>
+                    <prop key="displayName.ja">所属機関内電話番号</prop>
+                    <prop key="description.en">Business phone number: Office or campus phone number</prop>
+                    <prop key="description.de">Telefonnummer am Arbeitsplatz</prop>
+                    <prop key="description.fr">Teléphone de l'institut, de l'université</prop>
+                    <prop key="description.it">Numero di telefono dell'ufficio</prop>
+                    <prop key="description.ja">所属機関での利用者の電話番号</prop>
+                </props>
+            </property>
+        </bean>
+        
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">title</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:2.5.4.12</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:title</prop>
+                    <prop key="displayName.en">Title</prop>
+                    <prop key="displayName.de">Titel</prop>
+                    <prop key="displayName.fr">Title</prop>
+                    <prop key="displayName.ja">肩書き</prop>
+                    <prop key="description.en">Title of a person</prop>
+                    <prop key="description.de">Titel der Person</prop>
+                    <prop key="description.fr">Titre de la personne</prop>
+                    <prop key="description.ja">利用者の肩書き</prop>
+                </props>
+            </property>
+        </bean>
+        
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">uid</prop>
+                    <prop key="transcoder">SAML2StringTranscoder SAML1StringTranscoder</prop>
+                    <prop key="saml2.name">urn:oid:0.9.2342.19200300.100.1.1</prop>
+                    <prop key="saml1.name">urn:mace:dir:attribute-def:uid</prop>
+                    <prop key="displayName.en">User ID</prop>
+                    <prop key="displayName.de">Benutzer-ID</prop>
+                    <prop key="displayName.fr">ID utilisateur</prop>
+                    <prop key="displayName.it">ID dell'utente</prop>
+                    <prop key="displayName.ja">ユーザID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly used for user identification within the user's home organization.</prop>
+                    <prop key="description.de">Eine eindeutige Nummer für eine Person, welche hauptsächlich zur Identifikation innerhalb der Organisation benutzt wird.</prop>
+                    <prop key="description.fr">Identifiant de connexion d'une personnes sur les systèmes informatiques.</prop>
+                    <prop key="description.it">Identificativo unico della persona, usato per l'identificazione dell'utente all'interno della organizzazione di appartenenza.</prop>
+                    <prop key="description.ja">所属機関内で一意の利用者識別子</prop>
+                </props>
+            </property>
+        </bean>
+
+    </list>
+    </constructor-arg>
+    </bean>
+    
+</beans>
diff --git a/conf/attributes/samlSubject.xml b/conf/attributes/samlSubject.xml
new file mode 100644
index 0000000..dac9a59
--- /dev/null
+++ b/conf/attributes/samlSubject.xml
@@ -0,0 +1,67 @@
+<?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">
+
+    <!-- https://wiki.oasis-open.org/security/SAMLSubjectIDAttr -->
+
+    <bean parent="shibboleth.TranscodingRuleLoader">
+    <constructor-arg>
+    <list>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">samlSubjectID</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oasis:names:tc:SAML:attribute:subject-id</prop>
+                    <prop key="displayName.en">Unique ID</prop>
+                    <prop key="displayName.de">Eindeutige ID</prop>
+                    <prop key="displayName.fr">ID unique</prop>
+                    <prop key="displayName.it">ID unico</prop>
+                    <prop key="displayName.ja">サブジェクトID</prop>
+                    <prop key="description.en">A unique identifier for a person, mainly for inter-institutional user identification.</prop>
+                    <prop key="description.de">Eindeutige Benutzeridentifikation</prop>
+                    <prop key="description.de-ch">Eindeutige Benützeridentifikation</prop>
+                    <prop key="description.fr">Identifiant unique de l'utilisateur</prop>
+                    <prop key="description.it">Un identificativo personale che identifica chiaramente l'utente in seno alla sua organizzazione</prop>
+                    <prop key="description.ja">フェデレーション内で一意で永続的かつ難読化された利用者識別子(eduPersonUniqueIdの後継)</prop>
+                </props>
+            </property>
+        </bean>
+
+        <bean parent="shibboleth.TranscodingProperties">
+            <property name="properties">
+                <props merge="true">
+                    <prop key="id">samlPairwiseID</prop>
+                    <prop key="transcoder">SAML2ScopedStringTranscoder</prop>
+                    <prop key="saml2.name">urn:oasis:names:tc:SAML:attribute:pairwise-id</prop>
+                    <prop key="displayName.en">Pairwise ID</prop>
+                    <prop key="displayName.de">Pairwise ID</prop>
+                    <prop key="displayName.fr">Pairwise ID</prop>
+                    <prop key="displayName.it">Pairwise ID</prop>
+                    <prop key="displayName.ja">ペアワイズID</prop>
+                    <prop key="description.en">Pairwise ID: A unique identifier for a person, different for each service provider.</prop>
+                    <prop key="description.de">Pairwise ID: Eindeutige Benutzeridentifikation, unterschiedlich pro Service Provider.</prop>
+                    <prop key="description.de-ch">Pairwise ID: Eindeutige Benützeridentifikation, unterschiedlich pro Service Provider.</prop>
+                    <prop key="description.fr">Pairwise ID: Un identifiant unique de l'utilisateur, différent pour chaque fournisseur de service.</prop>
+                    <prop key="description.it">Pairwise ID: identificativo unico della persona, differente per ogni fornitore di servizio.</prop>
+                    <prop key="description.ja">フェデレーション内で一意かつSP毎に送出される値が異なる利用者識別子(eduPersonTargetedIDの後継)</prop>
+                </props>
+            </property>
+        </bean>
+
+    </list>
+    </constructor-arg>
+    </bean>
+    
+</beans>
diff --git a/conf/audit.xml b/conf/audit.xml
index 43f029d..42d82b8 100644
--- a/conf/audit.xml
+++ b/conf/audit.xml
@@ -11,16 +11,15 @@
     default-destroy-method="destroy">
 
     <!--
-    This bean defines a mapping between audit log categories and formatting strings. The default entry is
-    for compatibility with V2 audit logging.
+    This bean defines a mapping between audit log categories and formatting strings.
     -->
     <util:map id="shibboleth.AuditFormattingMap">
-        <entry key="Shibboleth-Audit" value="%T|%b|%I|%SP|%P|%IDP|%bb|%III|%u|%ac|%attr|%n|%i|%X" />
+        <entry key="Shibboleth-Audit" value="%a|%ST|%T|%u|%SP|%i|%ac|%t|%attr|%n|%f|%SSO|%XX|%XA|%b|%bb|%e|%S|%SS|%s|%UA" />
     </util:map>
 
     <!-- Override the format of date/time fields in the log and/or convert to default time zone. -->
     <!--
-    <bean id="shibboleth.AuditDateTimeFormat" class="java.lang.String" c:_0="YYYY-MM-dd'T'HH:mm:ss.SSSZZ" />
+    <bean id="shibboleth.AuditDateTimeFormat" class="java.lang.String" c:_0="yyyy-MM-dd'T'HH:mm:ss.SSSZZ" />
     <util:constant id="shibboleth.AuditDefaultTimeZone" static-field="java.lang.Boolean.TRUE" />
     -->
 
@@ -30,4 +29,23 @@
         <value>http://shibboleth.net/ns/profiles/mdquery</value>
     </util:list>
 
+    <util:map id="shibboleth.AuditFieldReplacementMap">
+        <entry key="urn:oasis:names:tc:SAML:1.0:am:password" value="password" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:ac:classes:Password" value="password" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" value="password" />
+        <entry key="urn:mace:shibboleth:1.0:nameIdentifier" value="transient" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" value="transient" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" value="persistent" />
+        <entry key="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" value="emailAddress" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:status:Success" value="Success" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:status:Requester" value="Requester" />
+        <entry key="urn:oasis:names:tc:SAML:2.0:status:Responder" value="Responder" />
+        <entry key="http://www.w3.org/2009/xmlenc11#aes128-gcm" value="AES128-GCM" />
+        <entry key="http://www.w3.org/2009/xmlenc11#aes192-gcm" value="AES192-GCM" />
+        <entry key="http://www.w3.org/2009/xmlenc11#aes256-gcm" value="AES256-GCM" />
+        <entry key="http://www.w3.org/2001/04/xmlenc#aes128-cbc" value="AES128-CBC" />
+        <entry key="http://www.w3.org/2001/04/xmlenc#aes192-cbc" value="AES192-CBC" />
+        <entry key="http://www.w3.org/2001/04/xmlenc#aes256-cbc" value="AES256-CBC" />
+    </util:map>
+
 </beans>
diff --git a/conf/authn/authn-comparison.xml b/conf/authn/authn-comparison.xml
index f167b7a..0730bcb 100644
--- a/conf/authn/authn-comparison.xml
+++ b/conf/authn/authn-comparison.xml
@@ -12,66 +12,106 @@
        default-destroy-method="destroy">
 
     <!--
-    These beans can be used in the AuthnComparisonRules map below instead of the defaults to
-    support more advanced matching rules. The top example shows how to configure a matching rule,
-    in this case a rule that the two listed classes are "better" than the password class.
-    
-    To use these beans, configure the matchingRules map as desired, and then reference the bean id in the
-    desired value-ref slot in the AuthnComparisonRules map.
+    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.
     -->
     
-    <bean id="shibboleth.BetterClassRefMatchFactory" parent="shibboleth.InexactMatchFactory">
-        <!--
-        <property name="matchingRules">
-            <map>
-                <entry key="urn:oasis:names:tc:SAML:2.0:ac:classes:Password">
-                    <list>
-                        <value>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</value>
-                        <value>urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken</value>
-                    </list>
-                </entry>
-            </map>
-        </property>
-        -->
-    </bean>
-
-    <bean id="shibboleth.MinimumClassRefMatchFactory" parent="shibboleth.InexactMatchFactory" />
-
-    <bean id="shibboleth.MaximumClassRefMatchFactory" parent="shibboleth.InexactMatchFactory" />
+    <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>
 
-    <!-- DeclRefs are rarely used in SAML, so you likely won't bother with these. -->
-    <bean id="shibboleth.BetterDeclRefMatchFactory" parent="shibboleth.InexactMatchFactory" />
-    <bean id="shibboleth.MinimumDeclRefMatchFactory" parent="shibboleth.InexactMatchFactory" />
-    <bean id="shibboleth.MaximumDeclRefMatchFactory" parent="shibboleth.InexactMatchFactory" />
-    
-    
-    <!-- Registry of matching rules. -->
-    
+    <!--
+    Uncomment and add entries to this map to support "inexact" SAML RequestedAuthnContext operators.
+    Please refer to the AuthenticationFlowSelection documentation topic for details and examples. 
+    -->
+    <!--
     <util:map id="shibboleth.AuthnComparisonRules">
-    
-        <!-- Exact matching, should be left alone to avoid tricking the IdP into behaving incorrectly. -->
-        <entry key-ref="shibboleth.SAMLAuthnMethodExact" value-ref="shibboleth.ExactMatchFactory"/>
-        <entry key-ref="shibboleth.SAMLACClassRefExact" value-ref="shibboleth.ExactMatchFactory"/>
-        <entry key-ref="shibboleth.SAMLACDeclRefExact" value-ref="shibboleth.ExactMatchFactory"/>
-
-        <!-- Minimum matching, leave to allow degeneration into exact, or replace with custom rules. -->
-        <entry key-ref="shibboleth.SAMLACClassRefMinimum" value-ref="shibboleth.ExactMatchFactory"/>
-        <entry key-ref="shibboleth.SAMLACDeclRefMinimum" value-ref="shibboleth.ExactMatchFactory"/>
-
-        <!-- Maximum matching, leave to allow degeneration into exact, or replace with custom rules. -->
-        <entry key-ref="shibboleth.SAMLACClassRefMaximum" value-ref="shibboleth.ExactMatchFactory"/>
-        <entry key-ref="shibboleth.SAMLACDeclRefMaximum" value-ref="shibboleth.ExactMatchFactory"/>
-
-        <!-- Better matching, refers to empty ruleset that has to be populated to work. -->
-        <entry key-ref="shibboleth.SAMLACClassRefBetter" value-ref="shibboleth.BetterClassRefMatchFactory"/>
-        <entry key-ref="shibboleth.SAMLACDeclRefBetter" value-ref="shibboleth.BetterDeclRefMatchFactory"/>
-        
     </util:map>
-    
+    -->
+
     <!-- List of context classes or declarations to ignore if an SP requests them. -->
 
     <util:list id="shibboleth.IgnoredContexts">
         <value>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</value>
     </util:list>
     
+    <!--
+    Mappings to transform custom Principals for proxied AuthnRequests.
+    Key is the input, value is a collection of possibly empty outputs.
+    Used by default to transform authentication type values from
+    SPs -> Proxied IdPs.
+    -->
+    <util:map id="shibboleth.PrincipalProxyRequestMappings">
+        <!--
+        <entry>
+            <key>
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:classRef="https://sp.example.org/context" />
+            </key>
+            <list>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context1" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context2" />
+            </list>
+        </entry>
+        <entry>
+            <key>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://sp.example.org/context" />
+            </key>
+            <list>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context1" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context2" />
+            </list>
+        </entry>
+        -->
+    </util:map>
+
+    <!--
+    Mappings to transform proxied Principals for inclusion in Subjects.
+    Key is the input, value is a collection of possibly empty outputs.
+    Used by default to transform values from Proxied IdP. -> 
+    -->
+    <util:map id="shibboleth.PrincipalProxyResponseMappings">
+        <!--
+        <entry>
+            <key>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context1" />
+            </key>
+            <list>
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:classRef="https://sp.example.org/context" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://sp.example.org/context" />
+            </list>
+        </entry>
+        <entry>
+            <key>
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://proxy.example.org/context2" />
+            </key>
+            <list>
+                <bean parent="shibboleth.SAML1AuthenticationMethod"
+                    c:classRef="https://sp.example.org/context" />
+                <bean parent="shibboleth.SAML2AuthnContextClassRef"
+                    c:classRef="https://sp.example.org/context" />
+            </list>
+        </entry>
+        -->
+    </util:map>
+    
 </beans>
diff --git a/conf/authn/authn.properties b/conf/authn/authn.properties
new file mode 100644
index 0000000..56111ef
--- /dev/null
+++ b/conf/authn/authn.properties
@@ -0,0 +1,213 @@
+# 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
+
+# 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
+# Most other settings need to be supplied via web.xml to the servlet
+
+#### 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
+# 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.
+#idp.authn.SAML.addDefaultPrincipals = false
+
+#### 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
diff --git a/conf/authn/duo-authn-config.xml b/conf/authn/duo-authn-config.xml
deleted file mode 100644
index 2867f48..0000000
--- a/conf/authn/duo-authn-config.xml
+++ /dev/null
@@ -1,29 +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">
-
-    <!--
-    By default, the Duo flow will use statically-defined integrations defined with the
-    duo.properties file. If you need more flexibility, you can define a function bean
-    called "shibboleth.authn.Duo.DuoIntegrationStrategy" to return an instance of
-    net.shibboleth.idp.authn.duo.DuoIntegration based on the state of the request.
-    A second bean, "shibboleth.authn.Duo.NonBrowser.DuoIntegrationStrategy", can be
-    supplied to use the AuthAPI for non-browser profiles.
-
-    The Duo flow is designed to operate in conjunction with some other login flow,
-    usually orchestrated by the MFA login flow. It obtains the username to send to
-    Duo based on the output of the other login flow or a previous session with the
-    user. You can override that approach using a function bean called
-    "shibboleth.authn.Duo.UsernameLookupStrategy" to supply the username from a
-    different source.
-    
-    Various other beans are supported, per the documentation.
-    -->
-
-</beans>
diff --git a/conf/authn/duo.properties b/conf/authn/duo.properties
deleted file mode 100644
index cb4b4aa..0000000
--- a/conf/authn/duo.properties
+++ /dev/null
@@ -1,30 +0,0 @@
-## Duo integration settings
-
-## Note: If upgrading from pre-3.3 IdP versions, you will need to manually add a pointer
-## to this property file to idp.properties.
-
-## The first set of properties support DuoWeb "iframe" integration.
-
-idp.duo.apiHost = hostname
-idp.duo.applicationKey = key
-idp.duo.integrationKey = key
-idp.duo.secretKey = key
-
-## The second set are used for direct AuthAPI usage for ECP support.
-## A seperate integration has to be created for this to work.
-
-#idp.duo.nonbrowser.apiHost = %{idp.duo.apiHost}
-#idp.duo.nonbrowser.applicationKey = key
-#idp.duo.nonbrowser.integrationKey = key
-#idp.duo.nonbrowser.secretKey = key
-
-## Request header names for Duo non-browser credentials.
-# idp.duo.nonbrowser.header.factor = X-Shibboleth-Duo-Factor
-# idp.duo.nonbrowser.header.device = X-Shibboleth-Duo-Device
-# idp.duo.nonbrowser.header.passcode = X-Shibboleth-Duo-Passcode
-
-## Enables auto selection of factor/device if not specified by client. 
-# idp.duo.nonbrowser.auto = true
-
-## Enables transmission of client address to Duo during authentication.
-# idp.duo.nonbrowser.clientAddressTrusted = true
diff --git a/conf/authn/external-authn-config.xml b/conf/authn/external-authn-config.xml
deleted file mode 100644
index 8b3a159..0000000
--- a/conf/authn/external-authn-config.xml
+++ /dev/null
@@ -1,70 +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">
-
-    <!-- Servlet context-relative path to wherever your implementation lives. -->
-    <bean id="shibboleth.authn.External.externalAuthnPath" class="java.lang.String"
-        c:_0="contextRelative:Authn/External" />
-
-    <!--
-    Default is to always use the path in the bean above. If you want to determine it
-    dynamically, define a bean called "shibboleth.authn.External.externalAuthnPathStrategy"
-    of type Function<ProfileRequestContext,String> that returns the path to use.
-    -->
-
-    <!--
-    Add authentication flow descriptor's supportedPrincipals collection to the resulting Subject?
-    You would normally only unset this if you plan to return a fully decorated Java Subject from your
-    external authentication source.
-    -->
-    <util:constant id="shibboleth.authn.External.addDefaultPrincipals" static-field="java.lang.Boolean.TRUE" />
-
-    <!--
-    <bean id="shibboleth.authn.External.matchExpression" class="java.util.regex.Pattern" factory-method="compile"
-        c:_0="^(.+)@example\.edu]$" />
-    -->
-
-    <!--
-    Define entries here to map error messages returned by external modules and classify them as particular
-    kinds of errors for use in your templates and as events in flows.
-
-    Keys are events to signal, values are error codes.
-
-    The examples here just allow external signaling of the exact type of condition to record.
-    
-    If you want to "fall-through" to other login flows, include a mapping to "ReselectFlow".
-    -->
-    <util:map id="shibboleth.authn.External.ClassifiedMessageMap">
-        <entry key="UnknownUsername">
-            <list>
-                <value>UnknownUsername</value>
-            </list>
-        </entry>
-        <entry key="InvalidPassword">
-            <list>
-                <value>InvalidPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiredPassword">
-            <list>
-                <value>ExpiredPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiringPassword">
-            <list>
-                <value>ExpiringPassword</value>
-            </list>
-        </entry>
-    </util:map>
-    
-</beans>
diff --git a/conf/authn/function-authn-config.xml b/conf/authn/function-authn-config.xml
deleted file mode 100644
index cf7876a..0000000
--- a/conf/authn/function-authn-config.xml
+++ /dev/null
@@ -1,37 +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">
-
-    <!--
-    Add authentication flow descriptor's supportedPrincipals collection to the resulting Subject?
-    You would normally only unset this if you plan to return a completely constructed Subject from
-    your authentication function.
-    -->
-    <util:constant id="shibboleth.authn.Function.addDefaultPrincipals" static-field="java.lang.Boolean.TRUE" />
-    
-    <!--
-    The entire flow depends on the execution of a function bean you supply. A pathological script example
-    is below. The function may return a String, Principal, Subject, or a null to signal failure.
-    -->
-    
-    <bean id="shibboleth.authn.Function.ResultLookupStrategy"
-            parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript">
-        <constructor-arg>
-            <value>
-            <![CDATA[
-                null;
-            ]]>
-            </value>
-        </constructor-arg>
-    </bean>    
-</beans>
diff --git a/conf/authn/general-authn.xml b/conf/authn/general-authn.xml
deleted file mode 100644
index 5699022..0000000
--- a/conf/authn/general-authn.xml
+++ /dev/null
@@ -1,158 +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/External" parent="shibboleth.AuthenticationFlow"
-            p:nonBrowserSupported="false" />
-
-        <bean id="authn/RemoteUser" parent="shibboleth.AuthenticationFlow"
-            p:nonBrowserSupported="false" />
-
-        <bean id="authn/RemoteUserInternal" parent="shibboleth.AuthenticationFlow" />
-
-        <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>
-
-    </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/conf/authn/ipaddress-authn-config.xml b/conf/authn/ipaddress-authn-config.xml
deleted file mode 100644
index a3ee096..0000000
--- a/conf/authn/ipaddress-authn-config.xml
+++ /dev/null
@@ -1,37 +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">
-
-
-    <!-- Apply any regular expression replacement pairs to address before validation. -->
-    <util:list id="shibboleth.authn.IPAddress.Transforms" />
-
-    <!--
-    Configure the address range(s) and principal name(s) for IP-based login here.
-    The ranges provided MUST be CIDR network expressions. To specify a single address,
-    add "/32" or "/128" for IPv4 or IPv6 respectively.
-    -->
-
-
-    <util:map id="shibboleth.authn.IPAddress.Mappings">
-        <!--
-        <entry key="jdoe">
-            <list>
-                <value>127.0.0.1/32</value>
-                <value>::1/128</value>
-            </list>
-        </entry>
-        -->
-    </util:map>
-
-</beans>
diff --git a/conf/authn/jaas-authn-config.xml b/conf/authn/jaas-authn-config.xml
deleted file mode 100644
index daef4d2..0000000
--- a/conf/authn/jaas-authn-config.xml
+++ /dev/null
@@ -1,27 +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">
-    
-    <!-- Specify your JAAS config. -->
-    <bean id="JAASConfig" class="org.springframework.core.io.FileSystemResource" c:path="%{idp.home}/conf/authn/jaas.config" />
-    
-    <util:property-path id="shibboleth.authn.JAAS.JAASConfigURI" path="JAASConfig.URI" />
-    
-    <!-- Specify the application name(s) in the JAAS config. -->
-    <util:list id="shibboleth.authn.JAAS.LoginConfigNames">
-        <value>ShibUserPassAuth</value>
-    </util:list>
-
-    <alias name="ValidateUsernamePasswordAgainstJAAS" alias="ValidateUsernamePassword"/>
-
-</beans>
diff --git a/conf/authn/jaas.config b/conf/authn/jaas.config
deleted file mode 100644
index 232e93d..0000000
--- a/conf/authn/jaas.config
+++ /dev/null
@@ -1,11 +0,0 @@
-ShibUserPassAuth {
-    /*
-	com.sun.security.auth.module.Krb5LoginModule required;
-	*/
-
-    org.ldaptive.jaas.LdapLoginModule required
-      ldapUrl="ldap://localhost:10389"
-      baseDn="ou=people,dc=example,dc=org"
-      userFilter="uid={user}";
-
-};
\ No newline at end of file
diff --git a/conf/authn/krb5-authn-config.xml b/conf/authn/krb5-authn-config.xml
deleted file mode 100644
index d3590a2..0000000
--- a/conf/authn/krb5-authn-config.xml
+++ /dev/null
@@ -1,31 +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">
-    
-    <util:constant id="shibboleth.authn.Krb5.RefreshConfig" static-field="java.lang.Boolean.FALSE" />
-
-    <util:constant id="shibboleth.authn.Krb5.PreserveTicket" static-field="java.lang.Boolean.FALSE" />
-
-    <!--
-    Uncomment these beans to perform KDC verification using a service principal and keytab.
-    The keytab bean must be an absolute file pathname and not a reference to a classpath resource,
-    so if idp.home is not a path, don't use it in the value.
-    -->
-    <!--
-    <bean id="shibboleth.authn.Krb5.ServicePrincipal" class="java.lang.String" c:_0="SERVICE/principal" />
-    <bean id="shibboleth.authn.Krb5.Keytab" class="java.lang.String" c:_0="%{idp.home}/credentials/keytab" />
-    -->
-    
-    <alias name="ValidateUsernamePasswordAgainstKerberos" alias="ValidateUsernamePassword"/>
-
-</beans>
diff --git a/conf/authn/ldap-authn-config.xml b/conf/authn/ldap-authn-config.xml
deleted file mode 100644
index 56d1bc7..0000000
--- a/conf/authn/ldap-authn-config.xml
+++ /dev/null
@@ -1,135 +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"
-       default-lazy-init="true">
-
-    <alias name="%{idp.authn.LDAP.authenticator:anonSearchAuthenticator}" alias="shibboleth.authn.LDAP.authenticator" />
-    <bean id="shibboleth.authn.LDAP.returnAttributes" parent="shibboleth.CommaDelimStringArray">
-        <constructor-arg type="java.lang.String" value="%{idp.authn.LDAP.returnAttributes:1.1}" />
-    </bean>
-
-    <alias name="ValidateUsernamePasswordAgainstLDAP" alias="ValidateUsernamePassword" />
-
-    <!-- Connection Configuration -->
-    <bean id="connectionConfig" class="org.ldaptive.ConnectionConfig" abstract="true" p:ldapUrl="%{idp.authn.LDAP.ldapURL}"
-        p:useStartTLS="%{idp.authn.LDAP.useStartTLS:true}"
-        p:useSSL="%{idp.authn.LDAP.useSSL:false}"
-        p:connectTimeoutDuration="%{idp.authn.LDAP.connectTimeout:PT3S}"
-        p:responseTimeoutDuration="%{idp.authn.LDAP.responseTimeout:PT3S}"
-        p:sslConfig-ref="sslConfig" />
-
-    <alias name="%{idp.authn.LDAP.sslConfig:certificateTrust}" alias="sslConfig" />
-
-    <bean id="jvmTrust" class="org.ldaptive.ssl.SslConfig" />
-    <bean id="certificateTrust" class="org.ldaptive.ssl.SslConfig">
-        <property name="credentialConfig">
-            <bean parent="shibboleth.X509ResourceCredentialConfig" p:trustCertificates="%{idp.authn.LDAP.trustCertificates:undefined}" /> 
-        </property>
-    </bean>
-    <bean id="keyStoreTrust" class="org.ldaptive.ssl.SslConfig">
-        <property name="credentialConfig">
-            <bean parent="shibboleth.KeystoreResourceCredentialConfig" p:truststore="%{idp.authn.LDAP.trustStore:undefined}" /> 
-        </property>
-    </bean>
-
-    <!-- Authentication handler -->
-    <bean id="authHandler" class="org.ldaptive.auth.PooledBindAuthenticationHandler" p:connectionFactory-ref="bindPooledConnectionFactory" />
-    <bean id="bindPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory" p:connectionPool-ref="bindConnectionPool" />
-    <bean id="bindConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
-        p:connectionFactory-ref="bindConnectionFactory" p:name="bind-pool" />
-    <bean id="bindConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindConnectionConfig" />
-    <bean id="bindConnectionConfig" parent="connectionConfig" />
-
-    <!-- Format DN resolution -->
-    <bean id="formatDnResolver" class="org.ldaptive.auth.FormatDnResolver" p:format="%{idp.authn.LDAP.dnFormat:undefined}" />
-
-    <!-- Pool Configuration -->
-    <bean id="connectionPool" class="org.ldaptive.pool.BlockingConnectionPool" abstract="true"
-        p:blockWaitTimeDuration="%{idp.pool.LDAP.blockWaitTime:PT3S}"
-        p:poolConfig-ref="poolConfig"
-        p:pruneStrategy-ref="pruneStrategy"
-        p:validator-ref="searchValidator"
-        p:failFastInitialize="%{idp.pool.LDAP.failFastInitialize:false}" />
-    <bean id="poolConfig" class="org.ldaptive.pool.PoolConfig"
-        p:minPoolSize="%{idp.pool.LDAP.minSize:3}"
-        p:maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
-        p:validateOnCheckOut="%{idp.pool.LDAP.validateOnCheckout:false}"
-        p:validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
-        p:validatePeriodDuration="%{idp.pool.LDAP.validatePeriod:PT5M}" />
-    <bean id="pruneStrategy" class="org.ldaptive.pool.IdlePruneStrategy"
-        p:prunePeriodDuration="%{idp.pool.LDAP.prunePeriod:PT5M}"
-        p:idleTimeDuration="%{idp.pool.LDAP.idleTime:PT10M}" />
-    <bean id="searchValidator" class="org.ldaptive.pool.SearchValidator" />
-
-    <!-- Anonymous Search Configuration -->
-    <bean name="anonSearchAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
-        <constructor-arg index="0" ref="anonSearchDnResolver" />
-        <constructor-arg index="1" ref="authHandler" />
-    </bean>
-    <bean id="anonSearchDnResolver" class="net.shibboleth.idp.authn.PooledTemplateSearchDnResolver"
-        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
-        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
-        p:connectionFactory-ref="anonSearchPooledConnectionFactory" >
-        <constructor-arg index="0" ref="shibboleth.VelocityEngine" />
-        <constructor-arg index="1" value="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}" />
-    </bean>
-    <bean id="anonSearchPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
-        p:connectionPool-ref="anonSearchConnectionPool" />
-    <bean id="anonSearchConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
-        p:connectionFactory-ref="anonSearchConnectionFactory" p:name="search-pool" />
-    <bean id="anonSearchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="anonSearchConnectionConfig" />
-    <bean id="anonSearchConnectionConfig" parent="connectionConfig" />
-
-    <!-- Bind Search Configuration -->
-    <bean name="bindSearchAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
-        <constructor-arg index="0" ref="bindSearchDnResolver" />
-        <constructor-arg index="1" ref="authHandler" />
-    </bean>
-    <bean id="bindSearchDnResolver" class="net.shibboleth.idp.authn.PooledTemplateSearchDnResolver"
-        p:baseDn="#{'%{idp.authn.LDAP.baseDN:undefined}'.trim()}"
-        p:subtreeSearch="%{idp.authn.LDAP.subtreeSearch:false}"
-        p:connectionFactory-ref="bindSearchPooledConnectionFactory" >
-        <constructor-arg index="0" ref="shibboleth.VelocityEngine" />
-        <constructor-arg index="1" value="#{'%{idp.authn.LDAP.userFilter:undefined}'.trim()}" />
-    </bean>
-    <bean id="bindSearchPooledConnectionFactory" class="org.ldaptive.pool.PooledConnectionFactory"
-        p:connectionPool-ref="bindSearchConnectionPool" />
-    <bean id="bindSearchConnectionPool" class="org.ldaptive.pool.BlockingConnectionPool" parent="connectionPool"
-        p:connectionFactory-ref="bindSearchConnectionFactory" p:name="search-pool" />
-    <bean id="bindSearchConnectionFactory" class="org.ldaptive.DefaultConnectionFactory" p:connectionConfig-ref="bindSearchConnectionConfig" />
-    <bean id="bindSearchConnectionConfig" parent="connectionConfig" p:connectionInitializer-ref="bindConnectionInitializer" />
-    <bean id="bindConnectionInitializer" class="org.ldaptive.BindConnectionInitializer"
-            p:bindDn="#{'%{idp.authn.LDAP.bindDN:undefined}'.trim()}">
-        <property name="bindCredential">
-            <bean class="org.ldaptive.Credential">
-                <constructor-arg value="%{idp.authn.LDAP.bindDNCredential:undefined}" />
-            </bean>
-        </property>
-    </bean>
-
-    <!-- Direct Search Configuration -->
-    <bean name="directAuthenticator" class="org.ldaptive.auth.Authenticator" p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
-        <constructor-arg index="0" ref="formatDnResolver" />
-        <constructor-arg index="1" ref="authHandler" />
-    </bean>
-
-    <!-- Want to use ppolicy? Configure support by adding <bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.PasswordPolicyAuthenticationResponseHandler" 
-        /> add p:authenticationResponseHandlers-ref="authenticationResponseHandler" to the authenticator <bean id="authenticationControl" 
-        class="org.ldaptive.control.PasswordPolicyControl" /> add p:authenticationControls-ref="authenticationControl" to the authHandler -->
-
-    <!-- Active Directory Configuration -->
-    <bean id="adAuthenticator" class="org.ldaptive.auth.Authenticator" p:authenticationResponseHandlers-ref="authenticationResponseHandler"
-        p:resolveEntryOnFailure="%{idp.authn.LDAP.resolveEntryOnFailure:false}">
-        <constructor-arg index="0" ref="formatDnResolver" />
-        <constructor-arg index="1" ref="authHandler" />
-    </bean>
-    <bean id="authenticationResponseHandler" class="org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler" />
-
-</beans>
diff --git a/conf/authn/mfa-authn-config.xml b/conf/authn/mfa-authn-config.xml
deleted file mode 100644
index f1b3918..0000000
--- a/conf/authn/mfa-authn-config.xml
+++ /dev/null
@@ -1,101 +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 is a map of transition rules that guide the behavior of the MFA flow
-    and controls how factors are sequenced, skipped, etc. The key of each entry
-    is the name of the step/flow out of which control is passing. The starting
-    rule has an empty key.
-    
-    Each entry is a bean inherited from "shibboleth.authn.MFA.Transition". Per
-    the Javadoc for net.shibboleth.idp.authn.MultiFactorAuthenticationTransition:
-            
-        p:nextFlow (String)
-            - A flow to run if the previous step signaled a "proceed" event, for simple
-                transitions.
-                
-        p:nextFlowStrategy (Function<ProfileRequestContext,String>)
-            - A function to run if the previous step signaled a "proceed" event, for dynamic
-                transitions. Returning null ends the MFA process.
-            
-        p:nextFlowStrategyMap (Map<String,Object> where Object is String or Function<ProfileRequestContext,String>)
-            - Fully dynamic way of expressing control paths. Map is keyed by a previously
-                signaled event and the value is a flow to run or a function to
-                return the flow to run. Returning null ends the MFA process.
-                
-    When no rule is provided, there's an implicit "null" that ends the MFA flow
-    with whatever event was last signaled. If the "proceed" event from a step is
-    the final event, then the MFA process attempts to complete itself successfully.
-    -->
-    <util:map id="shibboleth.authn.MFA.TransitionMap">
-        <!-- First rule runs the IPAddress login flow. -->
-        <entry key="">
-            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/IPAddress" />
-        </entry>
-        
-        <!--
-        Second rule runs a function if IPAddress succeeds, to determine whether an additional
-        factor is required.
-        -->
-        <entry key="authn/IPAddress">
-            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlowStrategy-ref="checkSecondFactor" />
-        </entry>
-        
-        <!-- An implicit final rule will return whatever the final flow returns. -->
-    </util:map>
-
-    <!-- Example script to see if second factor is required. -->
-    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
-        p:customObject-ref="shibboleth.AttributeResolverService">
-        <constructor-arg>
-            <value>
-            <![CDATA[
-                nextFlow = "authn/Password";
-
-                // Go straight to second factor if we have to, or set up for an attribute lookup first.
-                authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
-                mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
-                if (mfaCtx.isAcceptable()) {
-                    // Attribute check is required to decide if first factor alone is enough.
-                    resCtx = input.getSubcontext(
-                        "net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);
-                    rpCtx = input.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext");
-                    resCtx.setAttributeRecipientID(rpCtx.getRelyingPartyId());
-
-                    // Look up the username using a standard function.
-                    usernameLookupStrategyClass
-                        = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");
-                    usernameLookupStrategy = new usernameLookupStrategyClass();
-                    resCtx.setPrincipal(usernameLookupStrategy.apply(input));
-                        
-                    resCtx.getRequestedIdPAttributeNames().add("allowedLoginMethods");
-                    resCtx.resolveAttributes(custom);
-                    
-                    // Check for an attribute that authorizes use of first factor.
-                    attribute = resCtx.getResolvedIdPAttributes().get("allowedLoginMethods");
-                    valueType =  Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
-                    if (attribute != null && attribute.getValues().contains(new valueType("IPAddress"))) {
-                        nextFlow = null;
-                    }
-                    
-                    input.removeSubcontext(resCtx);   // cleanup
-                }
-                
-                nextFlow;   // pass control to second factor or end with the first
-            ]]>
-            </value>
-        </constructor-arg>
-    </bean>
-    
-</beans>
diff --git a/conf/authn/password-authn-config.xml b/conf/authn/password-authn-config.xml
index f27051b..4529b6f 100644
--- a/conf/authn/password-authn-config.xml
+++ b/conf/authn/password-authn-config.xml
@@ -12,29 +12,24 @@
        default-init-method="initialize"
        default-destroy-method="destroy">
     
-    <!-- Choose an import based on the back-end you want to use. -->
-    <!-- <import resource="jaas-authn-config.xml" /> -->
-    <!-- <import resource="krb5-authn-config.xml" /> -->
-    <import resource="ldap-authn-config.xml" />
-    
+    <!--
+    Ordered list of CredentialValidators to apply to a request.
     
-    <!-- Names of form fields to pull username and password from. -->
-    <bean id="shibboleth.authn.Password.UsernameFieldName" class="java.lang.String" c:_0="j_username" />
-    <bean id="shibboleth.authn.Password.PasswordFieldName" class="java.lang.String" c:_0="j_password" />
-    <bean id="shibboleth.authn.Password.SSOBypassFieldName" class="java.lang.String" c:_0="donotcache" />
-
-    <!-- Simple transforms to apply to username before validation. -->
-    <util:constant id="shibboleth.authn.Password.Lowercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.authn.Password.Uppercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.authn.Password.Trim" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Set to TRUE if you want the password kept in the resulting Subject as a private credential. -->
-    <util:constant id="shibboleth.authn.Password.RetainAsPrivateCredential" static-field="java.lang.Boolean.FALSE"/>
+    The four supplied variants are shown below; the HTPasswd option
+    is an OOB default for demo account purposes, and you will
+    want to remove it after initial install and testing.
+    -->
+    <util:list id="shibboleth.authn.Password.Validators">
+        <ref bean="shibboleth.LDAPValidator" />
+        <!-- <ref bean="shibboleth.KerberosValidator" /> -->
+        <!-- <ref bean="shibboleth.JAASValidator" /> -->
+        <!-- <bean parent="shibboleth.HTPasswdValidator" p:resource="%{idp.home}/credentials/demo.htpasswd" /> -->
+    </util:list>
 
     <!-- Apply any regular expression replacement pairs to username before validation. -->
     <util:list id="shibboleth.authn.Password.Transforms">
         <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
+        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.org$" p:second="$1" />
         -->
     </util:list>
     
@@ -47,7 +42,7 @@
         p:lockoutDuration="PT5M"
         p:extendLockoutDuration="false" />
     -->
-
+      
     <!--
     Define entries here to map error messages detected by validation actions and classify them as particular
     kinds of errors for use in your templates and as events in flows.
@@ -58,9 +53,15 @@
         <entry key="UnknownUsername">
             <list>
                 <value>NoCredentials</value>
+                <value>UnknownUsername</value>
                 <value>CLIENT_NOT_FOUND</value>
                 <value>Client not found</value>
+                <value>Cannot get kdc for realm</value>
+                <value>Client not found in Kerberos database</value>
                 <value>DN_RESOLUTION_FAILURE</value>
+                <value>Cannot authenticate dn, invalid dn</value>
+                <value>Cannot authenticate dn, invalid credential</value>
+                <value>AcceptSecurityContext error, data 525</value>
             </list>
         </entry>
         <entry key="InvalidPassword">
@@ -69,17 +70,31 @@
                 <value>PREAUTH_FAILED</value>
                 <value>INVALID_CREDENTIALS</value>
                 <value>Checksum failed</value>
+                <value>Integrity check on decrypted field failed</value>
+                <value>Pre-authentication information was invalid</value>
+                <value>Key bytes cannot be null</value>
+                <value>AcceptSecurityContext error, data 52e</value>
             </list>
         </entry>
         <entry key="AccountLocked">
             <list>
                 <value>AccountLocked</value>
                 <value>Clients credentials have been revoked</value>
+                <value>AcceptSecurityContext error, data 775</value>
+            </list>
+        </entry>
+        <entry key="AccountDisabled">
+            <list>
+                <value>AcceptSecurityContext error, data 533</value>
             </list>
         </entry>
         <entry key="ExpiredPassword">
             <list>
                 <value>PASSWORD_EXPIRED</value>
+                <value>CLIENT KEY EXPIRED</value>
+                <value>AcceptSecurityContext error, data 532</value>
+                <value>AcceptSecurityContext error, data 773</value>
+                <value>AcceptSecurityContext error, data 701</value>
             </list>
         </entry>
         <entry key="ExpiringPassword">
@@ -87,9 +102,17 @@
                 <value>ACCOUNT_WARNING</value>
             </list>
         </entry>
+        <entry key="RequestUnsupported">
+            <list>
+                <value>RequestUnsupported</value>
+            </list>
+        </entry>
     </util:map>
 
     <!--
+    WARNING: This set of features is generally discouraged in favor of the MFA flow,
+    and while not deprecated, is not recommended for new deployments.
+    
     Configuration of "extended" login methods to offer in the password login form.
     
     The String bean is a regular expression identifying the flows to offer. These flows
diff --git a/conf/authn/remoteuser-authn-config.xml b/conf/authn/remoteuser-authn-config.xml
deleted file mode 100644
index 4b7e722..0000000
--- a/conf/authn/remoteuser-authn-config.xml
+++ /dev/null
@@ -1,75 +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">
-
-    <!-- Servlet context-relative path to wherever your implementation lives. -->
-    <bean id="shibboleth.authn.RemoteUser.externalAuthnPath" class="java.lang.String"
-        c:_0="contextRelative:Authn/RemoteUser" />
-    
-    <!--
-    Default is to always use the path in the bean above. If you want to determine it
-    dynamically, define a bean called "shibboleth.authn.RemoteUser.externalAuthnPathStrategy"
-    of type Function<ProfileRequestContext,String> that returns the path to use.
-    -->
-
-    <!--
-    Add authentication flow descriptor's supportedPrincipals collection to the resulting Subject?
-    You would normally only unset this if you plan to use the authnMethodHeader servlet parameter to
-    supply authentication method string(s) from the external authentication system.
-    -->
-    <util:constant id="shibboleth.authn.RemoteUser.addDefaultPrincipals" static-field="java.lang.Boolean.TRUE" />
-
-    <!--
-    <bean id="shibboleth.authn.RemoteUser.matchExpression" class="java.util.regex.Pattern" factory-method="compile"
-        c:_0="^(.+)@example\.edu]$" />
-    -->
-
-    <!--
-    Define entries here to map error messages returned by external modules and classify them as particular
-    kinds of errors for use in your templates and as events in flows.
-
-    Keys are events to signal, values are error codes.
-
-    The examples here just allow external signaling of an exact condition.
-    
-    If you want to "fall-through" to other login flows, include a mapping to "ReselectFlow".
-    -->
-    <util:map id="shibboleth.authn.RemoteUser.ClassifiedMessageMap">
-        <entry key="ReselectFlow">
-            <list>
-                <value>NoCredentials</value>
-            </list>
-        </entry>
-        <entry key="UnknownUsername">
-            <list>
-                <value>UnknownUsername</value>
-            </list>
-        </entry>
-        <entry key="InvalidPassword">
-            <list>
-                <value>InvalidPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiredPassword">
-            <list>
-                <value>ExpiredPassword</value>
-            </list>
-        </entry>
-        <entry key="ExpiringPassword">
-            <list>
-                <value>ExpiringPassword</value>
-            </list>
-        </entry>
-    </util:map>
-    
-</beans>
diff --git a/conf/authn/remoteuser-internal-authn-config.xml b/conf/authn/remoteuser-internal-authn-config.xml
deleted file mode 100644
index 9e68c85..0000000
--- a/conf/authn/remoteuser-internal-authn-config.xml
+++ /dev/null
@@ -1,63 +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">
-
-    <!-- Check getRemoteUser() for identity (the typical case). -->
-    <util:constant id="shibboleth.authn.RemoteUser.checkRemoteUser" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Populate one or both of the lists below to define HTTP headers or Servlet Attributes to check. -->
-    
-    <util:list id="shibboleth.authn.RemoteUser.checkHeaders">
-        <!--
-        <value>User-Identity</value>
-        -->
-    </util:list>
-
-    <util:list id="shibboleth.authn.RemoteUser.checkAttributes">
-        <!--
-        <value>User-Identity</value>
-        -->
-    </util:list>
-    
-    <!-- Simple transforms to apply to username before validation. -->
-    <util:constant id="shibboleth.authn.RemoteUser.Lowercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.authn.RemoteUser.Uppercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.authn.RemoteUser.Trim" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Apply any regular expression replacement pairs before validation. -->
-    <util:list id="shibboleth.authn.RemoteUser.Transforms">
-        <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
-        -->
-    </util:list>
-    
-    <!-- Uncomment/configure to install username whitelist, blacklist, and/or match expressions. -->
-    
-    <util:list id="shibboleth.authn.RemoteUser.whitelistedUsernames">
-        <!--
-        <value>goodguy</value>
-        -->
-    </util:list>
-
-    <util:list id="shibboleth.authn.RemoteUser.blacklistedUsernames">
-        <!--
-        <value>badguy</value>
-        -->
-    </util:list>
-    
-    <!--
-    <bean id="shibboleth.authn.RemoteUser.matchExpression" class="java.util.regex.Pattern" factory-method="compile"
-        c:_0="^(.+)@example\.edu]$" />
-    -->
-    
-</beans>
diff --git a/conf/authn/spnego-authn-config.xml b/conf/authn/spnego-authn-config.xml
deleted file mode 100644
index 6c0fa48..0000000
--- a/conf/authn/spnego-authn-config.xml
+++ /dev/null
@@ -1,74 +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">
-
-    <!--  General Configuration -->
-
-    <!--
-    Enforce running SPNEGO for all users, independent of user's autologin state.
-    TRUE means that SPNEGO login is always tried (if available).
-    FALSE means that SPNEGO login is run only if the user has enabled autologin.
-    -->
-    <util:constant id="shibboleth.authn.SPNEGO.EnforceRun" static-field="java.lang.Boolean.FALSE" />
-   
-    <!-- Kerberos Configuration-->
-
-    <!-- General Kerberos Settings -->
-    
-    <util:constant id="shibboleth.authn.SPNEGO.Krb5.RefreshConfig" static-field="java.lang.Boolean.FALSE" />
-
-    <!--  Kerberos Service Principal(s) -->
-    
-    <!--
-    For each service principal/realm, a "RealmSettings" bean must be created.
-    For each "RealmSettings" bean, the following settings are supported:
-      p:servicePrincipal: - kerberos service principal (required)
-      p:keytab:           - path to the keytab file containing the kerberos service principal's credentials
-                            (optional; either "p:keytab" or "p:password" is required)
-      p:password:         - kerberos service principal's password
-                            (optional; either "p:keytab" or "p:password" is required)
-    -->
-    <util:list id="shibboleth.authn.SPNEGO.Krb5.Realms">
-
-        <bean parent="shibboleth.KerberosRealmSettings"
-            p:servicePrincipal="HTTP/aai-logon.domain_a.com@DOMAIN_A.COM"
-            p:keytab="%{idp.home}/credentials/http_domainA.keytab" />
-
-    </util:list>
-
-    <!--
-    <bean id="shibboleth.authn.SPNEGO.matchExpression" class="java.util.regex.Pattern" factory-method="compile"
-        c:_0="^(.+)@example\.edu$" />
-    -->
-
-    <!--
-    Define entries here to map events or error messages returned by the SPNEGO module
-    and classify them as particular kinds of errors for use in your templates and as
-    events in flows.
-
-    Keys are events to signal, values are error codes.
-    -->
-    <util:map id="shibboleth.authn.SPNEGO.ClassifiedMessageMap">
-        <entry key="SPNEGONotAvailable">
-            <list>
-                <value>SPNEGONotAvailable</value>
-            </list>
-        </entry>
-        <entry key="NTLMUnsupported">
-            <list>
-                <value>NTLMUnsupported</value>
-            </list>
-        </entry>
-    </util:map>
- 
-</beans>
diff --git a/conf/authn/x509-authn-config.xml b/conf/authn/x509-authn-config.xml
deleted file mode 100644
index 18b015a..0000000
--- a/conf/authn/x509-authn-config.xml
+++ /dev/null
@@ -1,44 +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">
-
-    <!-- Servlet context-relative path to wherever your implementation lives. -->
-    <bean id="shibboleth.authn.X509.externalAuthnPath" class="java.lang.String"
-        c:_0="contextRelative:x509-prompt.jsp" />
-
-    <!--
-    Default is to always use the path in the bean above. If you want to determine it
-    dynamically, define a bean called "shibboleth.authn.X509.externalAuthnPathStrategy"
-    of type Function<ProfileRequestContext,String> that returns the path to use.
-    -->
-
-    <!--
-    Define entries here to map error messages returned by external modules and classify them as particular
-    kinds of errors for use in your templates and as events in flows.
-
-    Keys are events to signal, values are error codes.
-    
-    The examples here just allow external signaling of an exact condition.
-    
-    If you want to "fall-through" to other login flows, include a mapping to "ReselectFlow".
-    -->
-    <util:map id="shibboleth.authn.X509.ClassifiedMessageMap">
-        <entry key="ReselectFlow">
-            <list>
-                <value>NoCredentials</value>
-                <value>InvalidCredentials</value>
-            </list>
-        </entry>
-    </util:map>
-    
-</beans>
diff --git a/conf/c14n/attribute-sourced-subject-c14n-config.xml b/conf/c14n/attribute-sourced-subject-c14n-config.xml
deleted file mode 100644
index 938b30f..0000000
--- a/conf/c14n/attribute-sourced-subject-c14n-config.xml
+++ /dev/null
@@ -1,44 +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">
-
-    <!--
-    A list of attributes to resolve for normalizing the subject. For example, you might
-    intend to lookup a uid in a directory based on what the user entered. You can make this
-    an empty list if you just want to resolve everything you normally would.
-    -->
-    <util:list id="shibboleth.c14n.attribute.AttributesToResolve">
-        <value>altuid</value>
-    </util:list>
-    
-    <!--
-    A list of attributes to search for a value to produce as the normalized subject name.
-    This will normally be something you resolve above.
-    -->
-    <util:list id="shibboleth.c14n.attribute.AttributeSourceIds">
-        <value>altuid</value>
-    </util:list>
-
-    <!-- Simple transforms to apply to attribute value used for canonicalization result. -->
-    <util:constant id="shibboleth.c14n.attribute.Lowercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.attribute.Uppercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.attribute.Trim" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Apply any regular expression replacement pairs. -->
-    <util:list id="shibboleth.c14n.attribute.Transforms">
-        <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
-        -->
-    </util:list>
-        
-</beans>
diff --git a/conf/c14n/simple-subject-c14n-config.xml b/conf/c14n/simple-subject-c14n-config.xml
deleted file mode 100644
index 3cddfa6..0000000
--- a/conf/c14n/simple-subject-c14n-config.xml
+++ /dev/null
@@ -1,27 +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">
-
-    <!-- Simple transforms to apply to username after authentication. -->
-    <util:constant id="shibboleth.c14n.simple.Lowercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.simple.Uppercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.simple.Trim" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Apply any regular expression replacement pairs after authentication. -->
-    <util:list id="shibboleth.c14n.simple.Transforms">
-        <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
-        -->
-    </util:list>
-        
-</beans>
diff --git a/conf/c14n/subject-c14n.properties b/conf/c14n/subject-c14n.properties
new file mode 100644
index 0000000..3811493
--- /dev/null
+++ b/conf/c14n/subject-c14n.properties
@@ -0,0 +1,40 @@
+# Properties that control the behavior of post-login subject c14n flows.
+# A few more advanced settings require XML configuration, see flow-specific docs.
+
+
+# Simple username -> principal name c14n
+#idp.c14n.simple.lowercase = false
+#idp.c14n.simple.uppercase = false
+#idp.c14n.simple.trim = true
+
+
+# Attribute resolution -> principal name c14n
+#idp.c14n.attribute.lowercase = false
+#idp.c14n.attribute.uppercase = false
+#idp.c14n.attribute.trim = true
+# Lists of attributes to resolve...
+#idp.c14n.attribute.attributesToResolve =
+#  and then select a principal name from
+#idp.c14n.attribute.attributeSourceIds =
+# Allows direct use of attributes via SAML proxy authn, bypasses resolver
+#idp.c14n.attribute.resolveFromSubject = false
+#idp.c14n.attribute.resolutionCondition = shibboleth.Conditions.TRUE
+
+# X.509 certificate -> principal name c14n
+#idp.c14n.x500.lowercase = false
+#idp.c14n.x500.uppercase = false
+#idp.c14n.x500.trim = true
+# Precedence is to check for a subjectAltName and then an OID RDN
+# Comma-delimited list of subjectAltName type numbers
+#  (See https://tools.ietf.org/html/rfc5280#section-4.2.1.6)
+#idp.c14n.x500.subjectAltNameTypes = 
+# Comma-delimited list of OIDS
+#idp.c14n.x500.objectIDs = 
+
+# Proxied SAML NameID -> principal name c14n
+#idp.c14n.saml.proxy.lowercase = false
+#idp.c14n.saml.proxy.uppercase = false
+
+# NameID consumption from SAML requests
+#idp.c14n.saml.lowercase = false
+#idp.c14n.saml.uppercase = false
diff --git a/conf/c14n/subject-c14n.xml b/conf/c14n/subject-c14n.xml
index 9740fdd..b354535 100644
--- a/conf/c14n/subject-c14n.xml
+++ b/conf/c14n/subject-c14n.xml
@@ -16,21 +16,36 @@
 
     <!--
     These are lists of Subject Canonicalization flows that turn complex Subject data into a string-based
-    principal name that the rest of the IdP can operate on. They're used both after authentication and
-    during operations like SAML attribute queries, to map the SAML Subject into a principal name. 
+    principal name that the rest of the IdP can operate on. They're used primarily after authentication
+    and also during less common operations like SAML attribute queries, to map the SAML Subject into a
+    principal name.
+    
     Flows are identified with an ID that corresponds to a Spring Web Flow subflow name.
+    
+    Most of the simple settings that configure these flows are in subject-c14n.properties.
     -->
 
-    <!-- Flows used after authentication to produce canonical principal name. -->
+    <!--
+    ====================================================================
+    Flows used after authentication to produce canonical principal name.
+    ====================================================================
+    -->
     <util:list id="shibboleth.PostLoginSubjectCanonicalizationFlows">
         <!--
         This is an advanced post-login step that performs attribute resolution and then produces a username
-        from an attribute value. Most of this configuration is handled by attribute-sourced-c14n-config.xml.
-        To enable universally, just uncomment, but if you want it to run under more specific conditions,
-        set an activationCondition property to a condition function to use to control when it should run. 
+        from an attribute value. To enable universally, just uncomment, but if you want it to run under more
+        specific conditions, set an activationCondition property to a condition to apply. 
         -->
         <!-- <bean id="c14n/attribute" parent="shibboleth.PostLoginSubjectCanonicalizationFlow" /> -->
 
+        <!--
+        This is an advanced option for use with SAML 2 proxy authentication to a second IdP that
+        derives the principal name semi-directly from the incoming NameID value. It is functionally
+        akin to the c14n/SAML2Transform flow for SAML Request scenarios, but separately defined so
+        a suitably restrictive format list and/or condition can be applied to it. 
+        -->
+        <!-- <ref bean="c14n/SAML2ProxyTransform" /> -->
+
         <!--
         This is an alternative that handles Subjects containing an X500Principal object and
         allows extraction from the DN.
@@ -40,24 +55,51 @@
         <!--
         This is the standard post-login step that returns a username derived from the login process. If you
         have more complex needs such as mapping a certificate DN into a principal name, an alternative may
-        be required such as that above, but you can configure simple transforms in simple-subject-c14n-config.xml
+        be required such as that above, but you can use this for simple transforms.
         -->
         <ref bean="c14n/simple" />
     </util:list>
     
+    <!-- What SAML NameID formats do you want to support direct transformations for while proxying? -->
+    <util:list id="shibboleth.ProxyNameTransformFormats">
+        <value>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</value>
+        <value>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</value>
+        <value>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</value>
+        <value>urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName</value>
+        <value>urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</value>
+    </util:list>
+    
     <!--
-    Flows used during SAML requests to reverse-map NameIdentifiers/NameIDs. The actual beans defining these
-    flows are in a system file. Below the list are some settings that might be useful to adjust.
+    Under what conditions should direct NameID mapping during proxying be allowed? By default, never.
+    Any condition can be used here; the example is suitable for enumerating a number of IdPs to allow.
     -->
-    <util:list id="shibboleth.SAMLSubjectCanonicalizationFlows">
-
+    <bean id="shibboleth.ProxyNameTransformPredicate" parent="shibboleth.Conditions.ProxyAuthentication">
+        <constructor-arg name="collection">
+            <list>
+                <!-- <value>https://idp-proxy.example.org</value> -->
+            </list>
+        </constructor-arg>
+    </bean>
+    
+    <!--
+    Regular expression transforms to apply to incoming proxied subject names. The default empty list just
+    echoes the name through unmodified.
+    -->
+    <util:list id="shibboleth.ProxyNameTransforms">
         <!--
-        This is installed to support the old mechanism of using PrincipalConnectors in the attribute resolver
-        to map SAML Subjects back into principals. If you don't use those (or this is a new install) you can
-        remove this.
+        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.org$" p:second="$1" />
         -->
-        <ref bean="c14n/LegacyPrincipalConnector" />
-        
+    </util:list>
+    
+    
+    <!--
+    =======================================================================
+    Flows used during SAML requests to reverse-map NameIdentifiers/NameIDs.
+    Below the list are some settings that might be useful to adjust.
+    =======================================================================
+    -->
+    <util:list id="shibboleth.SAMLSubjectCanonicalizationFlows">
+
         <!-- The next four are for handling transient IDs (in-storage and stateless variants). -->
         <ref bean="c14n/SAML2Transient" />
         <ref bean="c14n/SAML2CryptoTransient" />
@@ -102,7 +144,7 @@
     -->
     <util:list id="shibboleth.NameTransforms">
         <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
+        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.org$" p:second="$1" />
         -->
     </util:list>
     
diff --git a/conf/c14n/x500-subject-c14n-config.xml b/conf/c14n/x500-subject-c14n-config.xml
deleted file mode 100644
index 1ae25e4..0000000
--- a/conf/c14n/x500-subject-c14n-config.xml
+++ /dev/null
@@ -1,37 +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">
-
-    <!-- First priority is given to any subjectAltNames specified (emailAddress is 1) -->
-    <util:list id="shibboleth.c14n.x500.SubjectAltNameTypes">
-        <!-- <value>1</value> -->
-    </util:list>
-
-    <!-- Second priority is a list of Certificate Subject RDN OIDs to look for. -->
-    <util:list id="shibboleth.c14n.x500.ObjectIDs">
-        <value>2.5.4.3</value>
-    </util:list>
-
-    <!-- Simple transforms to apply to username after authentication. -->
-    <util:constant id="shibboleth.c14n.x500.Lowercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.x500.Uppercase" static-field="java.lang.Boolean.FALSE"/>
-    <util:constant id="shibboleth.c14n.x500.Trim" static-field="java.lang.Boolean.TRUE"/>
-
-    <!-- Apply any regular expression replacement pairs after authentication. -->
-    <util:list id="shibboleth.c14n.x500.Transforms">
-        <!--
-        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
-        -->
-    </util:list>
-        
-</beans>
diff --git a/conf/cas-protocol.xml b/conf/cas-protocol.xml
deleted file mode 100644
index 535cf0a..0000000
--- a/conf/cas-protocol.xml
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:c="http://www.springframework.org/schema/c"
-       xmlns:p="http://www.springframework.org/schema/p"
-       xmlns:util="http://www.springframework.org/schema/util"
-       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">
-
-    <!--
-       | The CAS service registry defines verified relying parties by endpoint URI.
-       | The default implementation treats the ID of each entry as a regular expression defining a logical group of
-       | services whose URIs match the expression.
-       |
-       | This bean is reloaded periodically according to %{idp.home}/conf/services.properties.
-       -->
-    <bean id="reloadableServiceRegistry"
-          class="%{idp.cas.serviceRegistryClass:net.shibboleth.idp.cas.service.PatternServiceRegistry}">
-        <property name="definitions">
-            <list>
-                <!--
-                <bean class="net.shibboleth.idp.cas.service.ServiceDefinition"
-                      c:regex="https://([A-Za-z0-9_-]+\.)*example\.org(:\d+)?/.*"
-                      p:group="proxying-services"
-                      p:authorizedToProxy="true"
-                      p:singleLogoutParticipant="true" />
-                <bean class="net.shibboleth.idp.cas.service.ServiceDefinition"
-                      c:regex="http://([A-Za-z0-9_-]+\.)*example\.org(:\d+)?/.*"
-                      p:group="non-proxying-services"
-                      p:authorizedToProxy="false" /
-                -->
-            </list>
-        </property>
-    </bean>
-
-    <!--
-       | Uncomment this bean if you want to override the default list of CAS service registries.
-       | The default configuration tries to find the relying party in a SAML metadata source and falls back to
-       | reloadableServiceRegistry if a match is not found.
-       -->
-    <!--<util:list id="shibboleth.CASServiceRegistries">
-        <ref bean="shibboleth.CASMetadataServiceRegistry" />
-        <ref bean="shibboleth.CASServiceRegistry" />
-    </util:list>-->
-
-    <!--
-       | The default ticket service as of 3.3.0 serializes ticket data into the opaque section of the ticket ID
-       | for service tickets and proxy tickets. Proxy-granting tickets still require server-side storage, and
-       | a StorageService defined by the idp.cas.StorageService is used. Thus for deployers that do not require
-       | CAS proxy capabilities, no stateful storage mechanism is required; that means no memcached or database
-       | is required for HA deployments that want CAS (without proxy) support. A notable limitation of the new
-       | component is that the one-time use feature of service and proxy tickets is not available due to the lack
-       | of a ticket-tracking mechanism. Instead, tickets expire when their expiration period is exceeded.
-       | If this limitation is of concern, one may consider decreasing ticketValidityPeriod on the profile
-       | configuration from the default 15000ms.
-       -->
-    <alias name="encodingTicketService" alias="shibboleth.CASTicketService" />
-
-    <!--
-       | Uncomment the following element and comment out the above to enable the previous default ticket service
-       | that uses a StorageService for ticket persistence. Use this if the one-time use limitation of
-       | EncodingTicketService is problematic and can't be mitigated by decreasing ticketValidityPeriod.
-       -->
-    <!--<alias name="simpleTicketService" alias="shibboleth.CASTicketService" /> -->
-
-    <!--
-       | The predicate used to determine whether IdP session validation is performed during the process of granting
-       | a proxy ticket. When the predicate evaluates to true, an IdP session is resolved and validated prior to
-       | granting a proxy ticket. This feature prevents issuing proxy tickets when an IdP session is expired, but comes
-       | at the cost of requiring server-side storage of IdP session data. If this is configured to a predicate that
-       | evaluates to true under any condition, a server-side storage service must be enabled for IdP session
-       | storage. The most common non-default value is "alwaysTrue."
-       -->
-    <bean id="shibboleth.CASProxyValidateIdPSessionPredicate"
-          class="com.google.common.base.Predicates"
-          factory-method="alwaysFalse" />
-
-    <!--
-       | Uncomment the following bean if you want to ignore jsessionid artifacts in service URLs.
-       | Those sorts of URLs are commonly emitted by Java servlet-based web applications.
-       -->
-    <!--<bean id="shibboleth.CASServiceComparator"
-          class="net.shibboleth.idp.cas.service.impl.DefaultServiceComparator"
-          c:parameterNames="[a-z]+sessionid" />-->
-
-    <!--
-       | Define the list of static certificates that you trust to secure CAS proxy callback endpoints.
-       | Typically these are CA certificates and apply to _all_ CAS proxy callback endpoints.
-       | This facility complements the capability to supply relying-party-specific certificates in SAML metadata,
-       | which is the preferred mechanism to specify CAS proxy trust material. In the case of metadata, self-signed
-       | certificates are recommended.
-       -->
-    <util:list id="shibboleth.CASProxyTrustedCertificates" value-type="java.lang.String">
-        <!--<value>%{idp.home}/credentials/your_ca.pem</value>-->
-    </util:list>
-
-
-    <!-- ============== Advanced CAS Configuration ============== -->
-
-    <!-- Configure a third-party ticket service. -->
-    <!--
-    <bean id="shibboleth.CASTicketService"
-          class="org.example.idp.cas.CustomTicketService" />
-    -->
-</beans>
\ No newline at end of file
diff --git a/conf/errors.xml b/conf/errors.xml
index a9f4074..a9730c0 100644
--- a/conf/errors.xml
+++ b/conf/errors.xml
@@ -26,8 +26,10 @@
         <entry key="ImpersonationViolation" value="true" />
         <entry key="AttributeReleaseRejected" value="true" />
         <entry key="TermsRejected" value="true" />
+        <entry key="EndpointResolutionFailed" value="true" />
         <entry key="RuntimeException" value="false" />
         <entry key="InvalidEvent" value="false" />
+        <entry key="InvalidCSRFToken" value="false" />
         <!--
         <entry key="IdentitySwitch" value="false" />
         <entry key="NoPotentialFlow" value="false" />
@@ -68,6 +70,7 @@
         
         <entry key="UnableToEncode" value-ref="shibboleth.SAML2Status.UnsupportedBinding" />
 
+        <entry key="AccessDenied" value-ref="shibboleth.SAML2Status.RequestDenied" />
         <entry key="MessageReplay" value-ref="shibboleth.SAML2Status.RequestDenied" />
         <entry key="MessageExpired" value-ref="shibboleth.SAML2Status.RequestDenied" />
         <entry key="MessageAuthenticationError" value-ref="shibboleth.SAML2Status.RequestDenied" />
@@ -88,6 +91,7 @@
         <entry key="SessionNotFound" value-ref="shibboleth.SAML2Status.UnknownPrincipal" />
         
         <entry key="InvalidNameIDPolicy" value-ref="shibboleth.SAML2Status.InvalidNameIDPolicy" />
+        <entry key="ProxyCountExceeded" value-ref="shibboleth.SAML2Status.ProxyCountExceeded" />
         
         <entry key="ChannelBindingsError" value-ref="shibboleth.SAML2Status.ChannelBindingsError" />
     </util:map>
diff --git a/conf/examples/attribute-resolver-ldap.xml b/conf/examples/attribute-resolver-ldap.xml
new file mode 100644
index 0000000..ec375b4
--- /dev/null
+++ b/conf/examples/attribute-resolver-ldap.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    This file is an EXAMPLE configuration file containing some example attributes
+    based on some commonly used approaches when LDAP is the principal data source.
+     
+    Not all attribute definitions or data connectors are demonstrated, but some
+    LDAP attributes common to Shibboleth deployments (and some not so common) are
+    included.
+
+    This example is in no way usable as a substitute for reading the documentation.    
+-->
+<AttributeResolver
+        xmlns="urn:mace:shibboleth:2.0:resolver"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+    <!-- ========================================== -->
+    <!--      Attribute Definitions                 -->
+    <!-- ========================================== -->
+
+    <!-- Simple attributes are exported directly from the LDAP connector. -->
+
+    <!-- eduPerson attributes requiring post-lookup manipulation -->
+<!-- 
+
+    <AttributeDefinition xsi:type="Prescoped" id="eduPersonPrincipalName">
+        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalName"/>
+    </AttributeDefinition>
+
+    <AttributeDefinition xsi:type="Prescoped" id="eduPersonPrincipalNamePrior">
+        <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalNamePrior"/>
+    </AttributeDefinition>
+
+    <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
+        <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
+    </AttributeDefinition>
+-->
+
+    <!-- Schema: SAML Subject ID Attributes -->
+<!--
+    <AttributeDefinition xsi:type="Scoped" id="samlSubjectID" scope="%{idp.scope}">
+        <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}"/>
+    </AttributeDefinition>
+
+    <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
+        <InputDataConnector ref="computed" attributeNames="computedId"/>
+    </AttributeDefinition>
+-->
+
+    <!-- ========================================== -->
+    <!--      Data Connectors                       -->
+    <!-- ========================================== -->
+
+    <!-- Example LDAP Connector -->
+
+    <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
+        ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
+        baseDN="%{idp.attribute.resolver.LDAP.baseDN}" 
+        principal="%{idp.attribute.resolver.LDAP.bindDN}"
+        principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
+        useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
+        connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
+        trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
+        responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
+        connectionStrategy="%{idp.attribute.resolver.LDAP.connectionStrategy}"
+        noResultIsError="true"
+        multipleResultsIsError="true"
+        excludeResolutionPhases="c14n/attribute"
+        exportAttributes="mail displayName sn givenName departmentNumber employeeNumber eduPersonEntitlement eduPersonAssurance">
+        <FilterTemplate>
+            <![CDATA[
+                %{idp.attribute.resolver.LDAP.searchFilter}
+            ]]>
+        </FilterTemplate>
+        <ConnectionPool
+            minPoolSize="%{idp.pool.LDAP.minSize:3}"
+            maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
+            blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
+            validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
+            validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
+            validateDN="%{idp.pool.LDAP.validateDN:}"
+            validateFilter="%{idp.pool.LDAP.validateFilter:(objectClass=*)}"
+            expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"/>
+    </DataConnector>
+
+    <!--
+    DataConnector for pairwise-id (example depends in part on saml-nameid.properties).
+    Note that this relies on BASE32 encoding in accordance with the attribute definition.
+    Older uses of this plugin for legacy eduPersonTargetedID/NameID values may require
+    different settings.
+    -->
+<!-- 
+    <DataConnector id="computed" xsi:type="ComputedId"
+        excludeResolutionPhases="c14n/attribute"
+	    generatedAttributeID="computedId"
+	    salt="%{idp.persistentId.salt}"
+	    algorithm="%{idp.persistentId.algorithm:SHA}"
+        encoding="BASE32">
+	    
+        <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
+        
+	</DataConnector>
+-->
+
+</AttributeResolver>
diff --git a/conf/global.xml b/conf/global.xml
index 457a814..c485f3f 100644
--- a/conf/global.xml
+++ b/conf/global.xml
@@ -15,23 +15,23 @@
     <!-- Use this file to define any custom beans needed globally. -->
 
     <!--
-    Algorithm whitelists and blacklists that override or merge with library defaults. Normally you can leave
-    these empty or commented and use the system defaults, but you can override those defaults using these lists.
-    Each <value> element is an algorithm URI, or you can use <util:constant> elements in place of literal values.
+    Algorithm include/exclude sets that override or merge with library defaults. Normally you can leave these
+    empty or commented and use the system defaults, but you can override those defaults using these beans.
+    Each <value> element is an algorithm URI; you can also use <util:constant> elements in place of literal values.
     -->
     
     <!--
-    <util:list id="shibboleth.SignatureWhitelist">
-    </util:list>
+    <util:set id="shibboleth.IncludedSignatureAlgorithms">
+    </util:set>
 
-    <util:list id="shibboleth.SignatureBlacklist">
-    </util:list>
+    <util:set id="shibboleth.ExcludedSignatureAlgorithms">
+    </util:set>
 
-    <util:list id="shibboleth.EncryptionWhitelist">
-    </util:list>
+    <util:set id="shibboleth.IncludedEncryptionAlgorithms">
+    </util:set>
 
-    <util:list id="shibboleth.EncryptionBlacklist">
-    </util:list>
+    <util:set id="shibboleth.ExcludedEncryptionAlgorithms">
+    </util:set>
     -->
 
     <!--
diff --git a/conf/idp.properties b/conf/idp.properties
index 783adfa..24c20d9 100644
--- a/conf/idp.properties
+++ b/conf/idp.properties
@@ -1,11 +1,15 @@
-# Load any additional property resources from a comma-delimited list
-idp.additionalProperties=/conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/authn/duo.properties
+# Auto-load all files matching conf/**/*.properties
+# Disable if you want to manually maintain a list of sources.
+idp.searchForProperties=true
+
+# Load any "outside-tree" property sources from a comma-delimited list
+idp.additionalProperties=/credentials/secrets.properties
 
 # In most cases (and unless noted in the surrounding comments) the
-# commented settings in the distributed files are the default
-# behavior for V3.
-#
+# commented settings in the distributed files document default behavior.
 # Uncomment them and change the value to change functionality.
+#
+# Uncommented properties are either required or ship non-defaulted.
 
 # Set the entityID of the IdP
 idp.entityID=https://idp.example.org/idp/shibboleth
@@ -18,12 +22,19 @@ idp.entityID=https://idp.example.org/idp/shibboleth
 idp.scope=example.org
 
 # General cookie properties (maxAge only applies to persistent cookies)
-# Note the default for idp.cookie.secure, you will usually want it set.
-#idp.cookie.secure = false
+#idp.cookie.secure = true
 #idp.cookie.httpOnly = true
 #idp.cookie.domain =
 #idp.cookie.path =
 #idp.cookie.maxAge = 31536000
+# These control operation of the SameSite filter, which is off by default.
+#idp.cookie.sameSite = None
+#idp.cookie.sameSiteCondition = shibboleth.Conditions.FALSE
+
+# Enable cross-site request forgery mitigation for views.
+idp.csrf.enabled=true
+# Name of the HTTP parameter that stores the CSRF token.
+#idp.csrf.token.parameter = csrf_token
 
 # HSTS/CSP response headers
 #idp.hsts = max-age=0
@@ -39,13 +50,12 @@ idp.scope=example.org
 #idp.views = %{idp.home}/views
 
 # Settings for internal AES encryption key
+#idp.sealer.keyStrategy = shibboleth.DataSealerKeyStrategy
 #idp.sealer.storeType = JCEKS
 #idp.sealer.updateInterval = PT15M
 #idp.sealer.aliasBase = secret
 idp.sealer.storeResource=%{idp.home}/credentials/sealer.jks
 idp.sealer.versionResource=%{idp.home}/credentials/sealer.kver
-idp.sealer.storePassword=changeit
-idp.sealer.keyPassword=changeit
 
 # Settings for public/private signing and encryption key(s)
 # During decryption key rollover, point the ".2" properties at a second
@@ -63,18 +73,21 @@ idp.encryption.cert=%{idp.home}/credentials/idp-encryption.crt
 # To downgrade to SHA-1, set to shibboleth.SigningConfiguration.SHA1
 #idp.signing.config = shibboleth.SigningConfiguration.SHA256
 
-# To upgrade to AES-GCM encryption, set to shibboleth.EncryptionConfiguration.GCM
-# This is unlikely to work for all SPs, but this is a quick way to test them.
-#idp.encryption.config = shibboleth.EncryptionConfiguration.CBC
+# The new install default for encryption is now AES-GCM.
+idp.encryption.config=shibboleth.EncryptionConfiguration.GCM
+
+# Sets the default strategy for key agreement key wrap usage for credentials from metadata,
+# if not otherwise configured on the security configuration
+#idp.encryption.keyagreement.metadata.defaultUseKeyWrap = Default
 
 # Configures trust evaluation of keys used by services at runtime
-# Defaults to supporting both explicit key and PKIX using SAML metadata.
-#idp.trust.signatures = shibboleth.ChainingSignatureTrustEngine
-# To pick only one set to one of:
-#   shibboleth.ExplicitKeySignatureTrustEngine, shibboleth.PKIXSignatureTrustEngine
-#idp.trust.certificates = shibboleth.ChainingX509TrustEngine
-# To pick only one set to one of:
-#   shibboleth.ExplicitKeyX509TrustEngine, shibboleth.PKIXX509TrustEngine
+# Internal default is Chaining, overriden for new installs
+idp.trust.signatures=shibboleth.ExplicitKeySignatureTrustEngine
+# Other options:
+#   shibboleth.ChainingSignatureTrustEngine, shibboleth.PKIXSignatureTrustEngine
+idp.trust.certificates=shibboleth.ExplicitKeyX509TrustEngine
+# Other options:
+#   shibboleth.ChainingX509TrustEngine, shibboleth.PKIXX509TrustEngine
 
 # If true, encryption will happen whenever a key to use can be located, but
 # failure to encrypt won't result in request failure.
@@ -82,7 +95,7 @@ idp.encryption.cert=%{idp.home}/credentials/idp-encryption.crt
 
 # Configuration of client- and server-side storage plugins
 #idp.storage.cleanupInterval = PT10M
-#idp.storage.htmlLocalStorage = false
+idp.storage.htmlLocalStorage=true
 
 # Set to true to expose more detailed errors in responses to SPs
 #idp.errors.detailed = false
@@ -112,34 +125,19 @@ idp.encryption.cert=%{idp.home}/credentials/idp-encryption.crt
 # Tolerate storage-related errors
 #idp.session.maskStorageFailure = false
 # Track information about SPs logged into
-#idp.session.trackSPSessions = false
+idp.session.trackSPSessions=true
 # Support lookup by SP for SAML logout
-#idp.session.secondaryServiceIndex = false
+idp.session.secondaryServiceIndex=true
 # Length of time to track SP sessions
 #idp.session.defaultSPlifetime = PT2H
 
-# Regular expression matching login flows to enable, e.g. IPAddress|Password
-idp.authn.flows=Password
-
-# Default lifetime and timeout of various authentication methods
-#idp.authn.defaultLifetime = PT60M
-#idp.authn.defaultTimeout = PT30M
-
-# 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
-
 # Set to "shibboleth.StorageService" or custom bean for alternate storage of consent
 #idp.consent.StorageService = shibboleth.ClientPersistentStorageService
 
+# Default consent auditing formats
+#idp.consent.terms-of-use.auditFormat = %T|%SP|%e|%u|%CCI|%CCV|%CCA
+#idp.consent.attribute-release.auditFormat = %T|%SP|%e|%u|%CCI|%CCV|%CCA
+
 # Set to "shibboleth.consent.AttributeConsentStorageKey" to use an attribute
 # to key user consent storage records (and set the attribute name)
 #idp.consent.attribute-release.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey
@@ -164,7 +162,18 @@ idp.authn.flows=Password
 #idp.consent.expandedMaxStoredRecords = 0
 
 # Time in milliseconds to expire consent storage records.
-#idp.consent.storageRecordLifetime = P1Y
+# Leave commented out for the default of infinite
+#idp.consent.storageRecordLifetime =
+
+# Path to use with External interceptor flow
+#idp.intercept.External.externalPath = contextRelative:intercept.jsp
+
+# Policies to use with Impersonate interceptor flow
+#idp.impersonate.generalPolicy = GeneralImpersonationPolicy
+#idp.impersonate.specificPolicy = SpecificImpersonationPolicy
+
+# Picks outbound bindings more sensibly than based on metadata order
+idp.bindings.inMetadataOrder=false
 
 # Whether to lookup metadata, etc. for every SP involved in a logout
 # for use by user interface logic; adds overhead so off by default.
@@ -173,6 +182,9 @@ idp.authn.flows=Password
 # Whether to require logout requests/responses be signed/authenticated.
 #idp.logout.authenticated = true
 
+# Bean to determine whether user should be allowed to cancel logout
+#idp.logout.promptUser=shibboleth.Conditions.FALSE
+
 # Message freshness and replay cache tuning
 #idp.policy.messageLifetime = PT3M
 #idp.policy.clockSkew = PT3M
@@ -194,19 +206,25 @@ idp.authn.flows=Password
 # browser-supported languages, defaults to an empty list.
 idp.ui.fallbackLanguages=en,fr,de
 
-# Storage service used by CAS protocol
+# Storage service used by CAS protocol for chained proxy-granting tickets
+# and when using server-managed "simple" TicketService.
 # Defaults to shibboleth.StorageService (in-memory)
 # MUST be server-side storage (e.g. in-memory, memcached, database)
-# NOTE that idp.session.StorageService requires server-side storage
-# when CAS protocol is enabled
 #idp.cas.StorageService=shibboleth.StorageService
 
 # CAS service registry implementation class
 #idp.cas.serviceRegistryClass=net.shibboleth.idp.cas.service.PatternServiceRegistry
 
+# If true, CAS services provisioned with SAML metadata are identified via entityID
+#idp.cas.relyingPartyIdFromMetadata=false
+
 # F-TICKS auditing - set a salt to include hashed username
-#idp.fticks.federation=MyFederation
-#idp.fticks.algorithm=SHA-256
-#idp.fticks.salt=somethingsecret
-#idp.fticks.loghost=localhost
-#idp.fticks.logport=514
+#idp.fticks.federation = MyFederation
+#idp.fticks.condition = MyFTICKSCondition
+#idp.fticks.algorithm = SHA-256
+#idp.fticks.salt = somethingsecret
+#idp.fticks.loghost = localhost
+#idp.fticks.logport = 514
+
+# Set false if you want SAML bindings "spelled out" in audit log
+idp.audit.shortenBindings=true
diff --git a/conf/intercept/consent-intercept-config.xml b/conf/intercept/consent-intercept-config.xml
deleted file mode 100644
index a089211..0000000
--- a/conf/intercept/consent-intercept-config.xml
+++ /dev/null
@@ -1,121 +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">
-
-    <!-- Terms of Use configuration -->
-    
-    <!--
-    Terms of use is driven by a lookup function returning a key into messages/consent-messages.properties
-    
-    The default mapping returns the relying party / SP name as the key. The second example below
-    demonstrates use of a custom mapping table from the relying party name to the key to use. 
-    -->
-    
-    <alias alias="shibboleth.consent.terms-of-use.Key" name="shibboleth.RelyingPartyIdLookup.Simple" />
-    
-    <!--
-    <bean id="shibboleth.consent.terms-of-use.Key"
-            class="com.google.common.base.Functions" factory-method="compose">
-        <constructor-arg name="g">
-            <bean class="com.google.common.base.Functions" factory-method="forMap" c:defaultValue="terms-of-use">
-                <constructor-arg name="map">
-                    <map>
-                        <entry key="https://sp.example.org/shibboleth" value="example-terms" />
-                    </map>
-                </constructor-arg>
-            </bean>
-        </constructor-arg>
-        <constructor-arg name="f">
-            <ref bean="shibboleth.RelyingPartyIdLookup.Simple" />
-        </constructor-arg>
-    </bean>
-    -->
-
-    <!-- Attribute Release configuration -->
-
-    <!--
-    Attribute release whitelist, blacklist, and match expressions to determine 
-    whether consent should be obtained for an attribute based on the attribute ID.
-    -->
-    
-    <util:list id="shibboleth.consent.attribute-release.WhitelistedAttributeIDs">
-        <!--
-        <value>mail</value>
-        -->
-    </util:list>
-
-    <util:list id="shibboleth.consent.attribute-release.BlacklistedAttributeIDs">
-        <value>transientId</value>
-        <value>persistentId</value>
-        <value>eduPersonTargetedID</value>
-    </util:list>
-
-    <!-- 
-    <bean id="shibboleth.consent.attribute-release.MatchExpression" class="java.util.regex.Pattern" factory-method="compile" 
-        c:_0="^exampleAttribute.*$" />
-    -->
-
-    <!--
-    Customize the order in which attributes are displayed.
-    Attribute IDs not present in this list will be sorted according to their
-    natural order and displayed subsequent to any attribute IDs specified here.
-    -->
-    <!--
-    <util:list id="shibboleth.consent.attribute-release.AttributeDisplayOrder">
-        <value>mail</value>
-    </util:list>
-    -->
-
-    <!--
-    These beans define mappings between audit log categories and formatting strings.
-    -->
-
-    <!--
-    For terms-of-use acceptance, the default entry is :
-     'YYYYMMDDTHHMMSSZ|TermsAccepted|jdoe|example-tou-1|rHo...rrw=|true'
-
-    For terms-of-use refusal, the default entry is :
-     'YYYYMMDDTHHMMSSZ|TermsRejected|jdoe|example-tou-1|rHo...rrw=|false'
-    -->
-    <util:map id="shibboleth.consent.terms-of-use.AuditFormattingMap">
-        <entry key="Shibboleth-Consent-Audit" value="%T|%SP|%e|%u|%CCI|%CCV|%CCA" />
-    </util:map>
-
-    <!--
-    For attribute-release consent, the default entry is :
-     'YYYYMMDDTHHMMSSZ|https://sp.example.org|AttributeReleaseConsent|jdoe|email,eduPersonAffiliation|rHo...rrw=,rHo...rrw=|false,false'
-    -->
-    <util:map id="shibboleth.consent.attribute-release.AuditFormattingMap">
-        <entry key="Shibboleth-Consent-Audit" value="%T|%SP|%e|%u|%CCI|%CCV|%CCA" />
-    </util:map>
-
-    <!--
-    Specify custom symbolic replacements for attribute names to shrink the size of results saved to client-side storage 
-    such as cookies.
-    -->
-    <bean id="shibboleth.consent.AttributeSymbolics" parent="shibboleth.consent.DefaultAttributeSymbolics" lazy-init="true">
-        <property name="sourceMap">
-            <map merge="true">
-                <!--
-                <entry key="myAttribute" value="900" />
-                -->
-            </map>
-        </property>
-    </bean>
-
-    <!--
-    Condition to evaluate to apply attribute-release consent to attribute queries.
-    -->
-    <bean id="shibboleth.consent.AttributeQuery.Condition" parent="shibboleth.Conditions.FALSE" />
-
-</beans>
\ No newline at end of file
diff --git a/conf/intercept/context-check-intercept-config.xml b/conf/intercept/context-check-intercept-config.xml
deleted file mode 100644
index aae07f0..0000000
--- a/conf/intercept/context-check-intercept-config.xml
+++ /dev/null
@@ -1,63 +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">
-
-    <!--
-    Condition to evaluate to interrupt SSO flows to check the state of the transaction before allowing.
-    
-    Typically the flow itself will be activated based on configuration in relying-party.xml, and this controls
-    whether to proceed if the flow is activated. The most common use for this flow is to check the set of
-    resolved/filtered attributes and values to see if the user is authorized or provisioned into a service.
-    -->
-    <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND">
-        <constructor-arg>
-            <list>
-                <bean parent="shibboleth.Conditions.RelyingPartyId" c:candidates="#{{'https://sp.example.org'}}" />
-                <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate"
-                        p:useUnfilteredAttributes="true">
-                    <property name="attributeValueMap">
-                        <map>
-                            <entry key="eppn">
-                                <list>
-                                    <value>*</value>
-                                </list>
-                            </entry>
-                        </map>
-                    </property>
-                </bean>
-            </list>
-        </constructor-arg>
-    </bean>
-
-    <!--
-    More general purpose approach using a Function that returns either "proceed" or a custom error Event.
-    This is a cleaner way of applying multiple conditions in different cases or triggering different events.
-    -->
-    <!--
-    <bean id="shibboleth.context-check.Function" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
-	        p:customObject-ref="shibboleth.context-check.Condition">
-        <constructor-arg>
-            <value>
-            <![CDATA[
-            var event = "proceed";
-            if (!custom.apply(input)) {
-                event = "ContextCheckDenied";
-            }
-            event;
-            ]]>
-            </value>
-        </constructor-arg>
-    </bean>
-    -->
-    
-</beans>
\ No newline at end of file
diff --git a/conf/intercept/expiring-password-intercept-config.xml b/conf/intercept/expiring-password-intercept-config.xml
deleted file mode 100644
index b3bf96d..0000000
--- a/conf/intercept/expiring-password-intercept-config.xml
+++ /dev/null
@@ -1,31 +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">
-
-    <!--
-    Condition to evaluate to determine if expiring password view should be displayed, false means to notify.
-    
-    The example uses a built-in class to evaluate an attribute containing a date/time of password expiration.
-    The format pattern parses the value and the negative offset determines how soon to warn the user beforehand.
-    -->
-    <bean id="shibboleth.expiring-password.Condition" class="net.shibboleth.idp.profile.logic.DateAttributePredicate"
-            c:attribute="passwordExpiration" c:formatString="yyyyMMddHHmmss'T'"
-            p:resultIfMissing="true" p:offset="-P14D" />
-    
-    <!-- Name of cookie to track when user was last notified. -->
-    <bean id="shibboleth.expiring-password.NotifyCookieName" class="java.lang.String" c:_0="shib_idp_exp_pwd" />
-
-    <!-- Interval (milliseconds) between notifications, default is 8 hours. -->
-    <bean id="shibboleth.expiring-password.NotifyInterval" class="java.lang.Long" c:_0="28800000" />
-    
-</beans>
diff --git a/conf/intercept/profile-intercept.xml b/conf/intercept/profile-intercept.xml
deleted file mode 100644
index 7b4c8aa..0000000
--- a/conf/intercept/profile-intercept.xml
+++ /dev/null
@@ -1,40 +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">
-
-    <!--
-    Intercept flows are used at various injection points to modify processing. This is the master list
-    of flows available that provide interesting features to deployers, but flows are actually enabled by
-    specifying them in various profile configuration beans via relying-party.xml 
-    
-    This list of flows is merged with a built-in set defined in a system configuration file, and may be
-    empty, but should not be removed. You must add your own custom flows to this list if you create any.
-    -->
-    
-    <bean id="shibboleth.AvailableInterceptFlows" parent="shibboleth.DefaultInterceptFlows" lazy-init="true">
-        <property name="sourceList">
-            <list merge="true">
-                <bean id="intercept/context-check" parent="shibboleth.InterceptFlow" />
-                
-                <bean id="intercept/expiring-password" parent="shibboleth.InterceptFlow" />
-        
-                <bean id="intercept/terms-of-use" parent="shibboleth.consent.TermsOfUseFlow" />
-        
-                <bean id="intercept/attribute-release" parent="shibboleth.consent.AttributeReleaseFlow" />
-                
-                <bean id="intercept/impersonate" parent="shibboleth.InterceptFlow" />
-            </list>
-        </property>
-    </bean>
-
-</beans>
diff --git a/conf/ldap.properties b/conf/ldap.properties
index 241aba1..45b0be0 100644
--- a/conf/ldap.properties
+++ b/conf/ldap.properties
@@ -7,11 +7,12 @@
 ## Connection properties ##
 idp.authn.LDAP.ldapURL=ldap://localhost:10389
 #idp.authn.LDAP.useStartTLS                     = true
-#idp.authn.LDAP.useSSL                          = false
 # Time in milliseconds that connects will block
 #idp.authn.LDAP.connectTimeout                  = PT3S
 # Time in milliseconds to wait for responses
 #idp.authn.LDAP.responseTimeout                 = PT3S
+# Connection strategy to use when multiple URLs are supplied, either ACTIVE_PASSIVE, ROUND_ROBIN, RANDOM
+#idp.authn.LDAP.connectionStrategy               = ACTIVE_PASSIVE
 
 ## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
 #idp.authn.LDAP.sslConfig                       = certificateTrust
@@ -33,20 +34,22 @@ idp.authn.LDAP.userFilter=(uid={user})
 # bind search configuration
 # for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
 idp.authn.LDAP.bindDN=uid=myservice,ou=system
-idp.authn.LDAP.bindDNCredential=myServicePassword
 
 # Format DN resolution, used by directAuthenticator, adAuthenticator
 # for AD use idp.authn.LDAP.dnFormat=%s@domain.com
 idp.authn.LDAP.dnFormat=uid=%s,ou=people,dc=example,dc=org
 
+# pool passivator, either none, bind or anonymousBind
+#idp.authn.LDAP.bindPoolPassivator                  = none
+
 # LDAP attribute configuration, see attribute-resolver.xml
 # Note, this likely won't apply to the use of legacy V2 resolver configurations
 idp.attribute.resolver.LDAP.ldapURL=%{idp.authn.LDAP.ldapURL}
 idp.attribute.resolver.LDAP.connectTimeout=%{idp.authn.LDAP.connectTimeout:PT3S}
 idp.attribute.resolver.LDAP.responseTimeout=%{idp.authn.LDAP.responseTimeout:PT3S}
+idp.attribute.resolver.LDAP.connectionStrategy=%{idp.authn.LDAP.connectionStrategy:ACTIVE_PASSIVE}
 idp.attribute.resolver.LDAP.baseDN=%{idp.authn.LDAP.baseDN:undefined}
 idp.attribute.resolver.LDAP.bindDN=%{idp.authn.LDAP.bindDN:undefined}
-idp.attribute.resolver.LDAP.bindDNCredential=%{idp.authn.LDAP.bindDNCredential:undefined}
 idp.attribute.resolver.LDAP.useStartTLS=%{idp.authn.LDAP.useStartTLS:true}
 idp.attribute.resolver.LDAP.trustCertificates=%{idp.authn.LDAP.trustCertificates:undefined}
 idp.attribute.resolver.LDAP.searchFilter=(uid=$resolutionContext.principal)
@@ -57,7 +60,8 @@ idp.attribute.resolver.LDAP.searchFilter=(uid=$resolutionContext.principal)
 #idp.pool.LDAP.validateOnCheckout               = false
 #idp.pool.LDAP.validatePeriodically             = true
 #idp.pool.LDAP.validatePeriod                   = PT5M
+#idp.pool.LDAP.validateDN                       =
+#idp.pool.LDAP.validateFilter                   = (objectClass=*)
 #idp.pool.LDAP.prunePeriod                      = PT5M
 #idp.pool.LDAP.idleTime                         = PT10M
 #idp.pool.LDAP.blockWaitTime                    = PT3S
-#idp.pool.LDAP.failFastInitialize               = false
diff --git a/conf/logback.xml b/conf/logback.xml
index 2bf2c2b..bf38b44 100644
--- a/conf/logback.xml
+++ b/conf/logback.xml
@@ -60,7 +60,6 @@
     <logger name="net.shibboleth.idp.log.LogbackLoggingService" level="${idp.loglevel.props}" />
 
     <!-- Especially chatty. -->
-    <logger name="net.shibboleth.idp.saml.attribute.mapping" level="INFO" />
     <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec}" />
     <logger name="org.springframework" level="${idp.loglevel.spring}"/>
     <logger name="org.apache.catalina" level="${idp.loglevel.container}"/>
@@ -86,7 +85,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -110,7 +109,7 @@
         
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
             <charset>UTF-8</charset>
-            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{full}</Pattern>
         </encoder>
         
         <!-- Ignore Velocity status page error. -->
@@ -118,7 +117,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -173,4 +172,4 @@
         <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
     </root>
 
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/conf/logback.xml.dist b/conf/logback.xml.dist
index cda207e..730f583 100644
--- a/conf/logback.xml.dist
+++ b/conf/logback.xml.dist
@@ -60,7 +60,6 @@
     <logger name="net.shibboleth.idp.log.LogbackLoggingService" level="${idp.loglevel.props}" />
 
     <!-- Especially chatty. -->
-    <logger name="net.shibboleth.idp.saml.attribute.mapping" level="INFO" />
     <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec}" />
     <logger name="org.springframework" level="${idp.loglevel.spring}"/>
     <logger name="org.apache.catalina" level="${idp.loglevel.container}"/>
@@ -90,7 +89,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -118,7 +117,7 @@
         
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
             <charset>UTF-8</charset>
-            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{full}</Pattern>
         </encoder>
         
         <!-- Ignore Velocity status page error. -->
@@ -126,7 +125,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -189,4 +188,4 @@
         <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
     </root>
 
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/conf/logback.xml.tmp3 b/conf/logback.xml.tmp3
index 88c28eb..4674e93 100644
--- a/conf/logback.xml.tmp3
+++ b/conf/logback.xml.tmp3
@@ -60,7 +60,6 @@
     <logger name="net.shibboleth.idp.log.LogbackLoggingService" level="${idp.loglevel.props}" />
 
     <!-- Especially chatty. -->
-    <logger name="net.shibboleth.idp.saml.attribute.mapping" level="INFO" />
     <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec}" />
     <logger name="org.springframework" level="${idp.loglevel.spring}"/>
     <logger name="org.apache.catalina" level="${idp.loglevel.container}"/>
@@ -90,7 +89,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -118,7 +117,7 @@
         
         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
             <charset>UTF-8</charset>
-            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+            <Pattern>%date{ISO8601} - %mdc{idp.remote_addr} - %level [%logger:%line] - %msg%n%ex{full}</Pattern>
         </encoder>
         
         <!-- Ignore Velocity status page error. -->
@@ -126,7 +125,7 @@
             <evaluator>
                 <matcher>
                     <Name>VelocityStatusMatcher</Name>
-                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                    <regex>ResourceManager\s*: unable to find resource 'status\.vm' in any resource loader\.</regex>
                 </matcher>
                 <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
             </evaluator>
@@ -189,4 +188,4 @@
         <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
     </root>
 
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/conf/metadata-providers.xml b/conf/metadata-providers.xml
index d723005..d5cb34b 100644
--- a/conf/metadata-providers.xml
+++ b/conf/metadata-providers.xml
@@ -1,29 +1,39 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- This file is an EXAMPLE metadata configuration file. -->
 <MetadataProvider id="ShibbolethMetadata" xsi:type="ChainingMetadataProvider"
     xmlns="urn:mace:shibboleth:2.0:metadata"
-    xmlns:resource="urn:mace:shibboleth:2.0:resource"
     xmlns:security="urn:mace:shibboleth:2.0:security"
+    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
     xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+    xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport"
+    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+    xmlns:ds11="http://www.w3.org/2009/xmldsig11#"
+    xmlns:enc="http://www.w3.org/2001/04/xmlenc#"
+    xmlns:enc11="http://www.w3.org/2009/xmlenc11#"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd
-                        urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd 
                         urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd
-                        urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd">
-
-    <!-- ========================================================================================== -->
-    <!--                             Metadata Configuration                                         -->
-    <!--                                                                                            -->
-    <!--  Below you place the mechanisms which define how to load the metadata for SP(s) you will   -->
-    <!--  provide service to.                                                                       -->
-    <!--                                                                                            -->
-    <!--  Two examples are provided.  The Shibboleth Documentation at                               -->
-    <!--  https://wiki.shibboleth.net/confluence/display/IDP30/MetadataConfiguration                -->
-    <!--  provides more details.                                                                    --> 
-    <!--                                                                                            -->
-    <!--  NOTE.  This file SHOULD NOT contain the metadata for this IdP.                            -->
-    <!-- ========================================================================================== -->
+                        urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd
+                        urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd
+                        urn:oasis:names:tc:SAML:metadata:algsupport http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0.xsd
+                        http://www.w3.org/2000/09/xmldsig# http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd
+                        http://www.w3.org/2009/xmldsig11# http://www.w3.org/TR/2013/REC-xmldsig-core1-20130411/xmldsig11-schema.xsd
+                        http://www.w3.org/2001/04/xmlenc# http://www.w3.org/TR/xmlenc-core/xenc-schema.xsd
+                        http://www.w3.org/2009/xmlenc11# http://www.w3.org/TR/2013/REC-xmlenc-core1-20130411/xenc-schema-11.xsd"
+    sortKey="1">
 
+    <!--
+    Below you place the mechanisms which define how to load the metadata for SP(s) you will
+    provide service to.
+    
+    Some simple examples are provided. The documentation provides more details; in most cases,
+    the modern replacement for these older plugins are the "DynamicHTTPMetadataProvider" and
+    "LocalDynamic" variants, which provide dramatic memory savings and more reliable operation.
+     
+    NOTE: You do NOT need to load metadata for this IdP itself within this configuration.
+    -->
+    
+    
+    
     <!--
     Example HTTP metadata provider.  Use this if you want to download the metadata
     from a remote source.
@@ -32,19 +42,20 @@
     Get the public key certificate from the party publishing the metadata, and validate
     it with them via some out of band mechanism (e.g., a fingerprint on a secure page).
 
-    The EntityRoleWhiteList saves memory by only loading metadata from SAML roles
-    that the IdP needs to interoperate with. 
+    The EntityRole filter saves memory by only loading metadata from SAML roles
+    that the IdP needs to interoperate with.
     -->
     
     <!--
     <MetadataProvider id="HTTPMetadata"
                       xsi:type="FileBackedHTTPMetadataProvider"
                       backingFile="%{idp.home}/metadata/localCopyFromXYZHTTP.xml"
-                      metadataURL="http://WHATEVER"> 
+                      metadataURL="http://WHATEVER"
+                      failFastInitialization="false">
         
         <MetadataFilter xsi:type="SignatureValidation" certificateFile="%{idp.home}/credentials/metaroot.pem" />
         <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D"/>
-        <MetadataFilter xsi:type="EntityRoleWhiteList">
+        <MetadataFilter xsi:type="EntityRole">
             <RetainedRole>md:SPSSODescriptor</RetainedRole>
         </MetadataFilter>
     </MetadataProvider>
@@ -52,8 +63,8 @@
 
     <!--
     Example file metadata provider.  Use this if you want to load metadata
-    from a local file.  You might use this if you have some local SPs
-    which are not "federated" but you wish to offer a service to.
+    from a local file. You use this if you have some local SPs which are not
+    "federated" but you wish to offer a service to.
     
     If you do not provide a SignatureValidation filter, then you have the
     responsibility to ensure that the contents on disk are trustworthy.
@@ -65,11 +76,11 @@
 
 
     <!--
-    Example CAS metadata source.
+    Example CAS metadata source for managing CAS services using SAML metadata.
     -->
 
     <!--
-    <MetadataProvider id="CasMetadata"
+    <MetadataProvider id="CASMetadata"
                       xsi:type="FilesystemMetadataProvider"
                       metadataFile="PATH_TO_YOUR_METADATA"
                       indexesRef="shibboleth.CASMetadataIndices" />
diff --git a/conf/relying-party.xml b/conf/relying-party.xml
index 28c9193..439e7f1 100644
--- a/conf/relying-party.xml
+++ b/conf/relying-party.xml
@@ -27,20 +27,22 @@
         </property>
     </bean>
 
-    <!--
-    Default configuration, with default settings applied for all profiles, and enables
-    the attribute-release consent flow.
-    -->
+    <!-- Default configuration, with default settings applied for all profiles. -->
     <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
         <property name="profileConfigurations">
             <list>
-                <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" />
+                <!-- SAML 1.1 and SAML 2.0 AttributeQuery are disabled by default. -->
+                <!--
+                <bean parent="Shibboleth.SSO" />
                 <ref bean="SAML1.AttributeQuery" />
                 <ref bean="SAML1.ArtifactResolution" />
-                <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" />
+                -->
+                <bean parent="SAML2.SSO" />
                 <ref bean="SAML2.ECP" />
                 <ref bean="SAML2.Logout" />
+                <!--
                 <ref bean="SAML2.AttributeQuery" />
+                -->
                 <ref bean="SAML2.ArtifactResolution" />
                 <ref bean="Liberty.SSOS" />
             </list>
@@ -56,7 +58,7 @@
         for SAML 2 SSO without encryption. This is a common "vendor" scenario.
         -->
         <!--
-        <bean parent="RelyingPartyByName" c:relyingPartyIds="https://sp.example.org">
+        <bean id="ExampleSP" parent="RelyingPartyByName" c:relyingPartyIds="https://sp.example.org">
             <property name="profileConfigurations">
                 <list>
                     <bean parent="SAML2.SSO" p:encryptAssertions="false" />
diff --git a/conf/saml-nameid.properties b/conf/saml-nameid.properties
index bbc1597..7169c5e 100644
--- a/conf/saml-nameid.properties
+++ b/conf/saml-nameid.properties
@@ -4,10 +4,6 @@
 # identifiers. See saml-nameid.xml and c14n/subject-c14n.xml for advanced
 # settings
 
-# Comment out to disable legacy NameID generation via Attribute Resolver
-#idp.nameid.saml2.legacyGenerator = shibboleth.LegacySAML2NameIDGenerator
-#idp.nameid.saml1.legacyGenerator = shibboleth.LegacySAML1NameIdentifierGenerator
-
 # Default NameID Formats to use when nothing else is called for.
 # Don't change these just to change the Format used for a single SP!
 #idp.nameid.saml2.default = urn:oasis:names:tc:SAML:2.0:nameid-format:transient
@@ -18,12 +14,10 @@
 
 # Persistent IDs can be computed on the fly with a hash, or managed in a database
 
-# For computed IDs, set a source attribute and a secret salt:
+# For computed IDs, set a source attribute, and a secret salt in secrets.properties
 #idp.persistentId.sourceAttribute = changethistosomethingreal
 #idp.persistentId.useUnfilteredAttributes = true
-# Do *NOT* share the salt with other people, it's like divulging your private key.
 #idp.persistentId.algorithm = SHA
-#idp.persistentId.salt = changethistosomethingrandom
 # BASE64 will match V2 values, we recommend BASE32 encoding for new installs.
 idp.persistentId.encoding = BASE32
 
diff --git a/conf/services.properties b/conf/services.properties
index 0aa9007..8150d3a 100644
--- a/conf/services.properties
+++ b/conf/services.properties
@@ -12,14 +12,23 @@
 #idp.service.logging.failFast = true
 idp.service.logging.checkInterval = PT5M
 
-# Set to shibboleth.LegacyRelyingPartyResolverResources with legacy V2 relying-party.xml
 #idp.service.relyingparty.resources = shibboleth.RelyingPartyResolverResources
 #idp.service.relyingparty.failFast = false
 idp.service.relyingparty.checkInterval = PT15M
+# See MetadataDrivenConfiguration wiki topic for details
+idp.service.relyingparty.ignoreUnmappedEntityAttributes=true
 
 #idp.service.metadata.resources = shibboleth.MetadataResolverResources
 #idp.service.metadata.failFast = false
 #idp.service.metadata.checkInterval = PT0S
+# Set to false if not using ByReference MetadataFilters for a small perf gain
+#idp.service.metadata.enableByReferenceFilters = true
+
+#idp.service.attribute.registry.resources = shibboleth.AttributeRegistryResources
+#idp.service.attribute.registry.failFast = false
+idp.service.attribute.registry.checkInterval = PT15M
+# Default control of whether to encode XML attribute data with xsi:type
+idp.service.attribute.registry.encodeType = false
 
 #idp.service.attribute.resolver.resources = shibboleth.AttributeResolverResources
 #idp.service.attribute.resolver.failFast = false
@@ -45,12 +54,15 @@ idp.service.access.checkInterval = PT5M
 #idp.service.cas.registry.failFast = false
 idp.service.cas.registry.checkInterval = PT15M
 
+#idp.service.managedBean.resources = shibboleth.ManagedBeanResources
+#idp.service.managedBean.failFast = false
+idp.service.managedBean.checkInterval = PT15M
+
 #idp.message.resources = shibboleth.MessageSourceResources
 #idp.message.cacheSeconds = 300
 
-# Parameters for pre-defined HttpClient instances which perform in-memory and filesystem caching.
-# These are used with components such as remote configuration resources that are explicitly wired
-# with these client instances, *not* by default with HTTP metadata resolvers.
+# These settings impact the behavior of the internal HTTP Client used by default
+# with some internal components, but notably *not* for metadata acquisition.
 #idp.httpclient.useSecurityEnhancedTLSSocketFactory = false
 #idp.httpclient.connectionDisregardTLSCertificate = false
 #idp.httpclient.connectionRequestTimeout = PT1M
@@ -58,6 +70,11 @@ idp.service.cas.registry.checkInterval = PT15M
 #idp.httpclient.socketTimeout = PT1M
 #idp.httpclient.maxConnectionsTotal = 100
 #idp.httpclient.maxConnectionsPerRoute = 100
+
+# These are deprecated properties that configure the old caching HttpClient
+# beans that are no longer supported. If you want to manually configure
+# the caching clients, you should define the beans yourself and if desired
+# rely on properties of your own devising.
 #idp.httpclient.memorycaching.maxCacheEntries = 50
 #idp.httpclient.memorycaching.maxCacheEntrySize = 1048576
 #idp.httpclient.filecaching.maxCacheEntries = 100
diff --git a/conf/services.xml b/conf/services.xml
index e04ac8f..24e2b1e 100644
--- a/conf/services.xml
+++ b/conf/services.xml
@@ -9,82 +9,41 @@
     default-init-method="initialize"
     default-destroy-method="destroy">
                                
-    <!-- Advanced configuration of services from HTTP.
-    
-      To use an HTTP resource you first need to configure the Apache HttpClient which will be used
-      to communicate with the web server.  Any HttpClient can be used, but two Factory Beans allow simple
-      configuration of in-memory or file-based caching clients.
-      
-      Examples are:
-      
-        A resource which will be supplied from an in-memory cache for as long as the file on the webserver does not change.  
-        If the webserver becomes unavailable the resource will be unavailable.
-         
-        <bean id="inMemoryResource" class="net.shibboleth.ext.spring.resource.HTTPResource"
-              c:client-ref="shibboleth.MemoryCachingHttpClient" 
-              c:url="http://example.org/path/to/file.xml" />
-              
-        Two resources which will be supplied from an on disk cache (suitable for multiple or large files) for as long 
-        as the file on the webserver does not change.  If the webserver becomes unavailable the last used contents
-        of the file will be returned (even if that was in a previous IdP lifetime).
-        
-        <bean id="fileResource" class="net.shibboleth.ext.spring.resource.FileBackedHTTPResource"
-              c:client-ref="shibboleth.FileCachingHttpClient" 
-              c:url="http://example.org/path/to/file.xml"
-              c:backingFile="/var/shibboleth/caches/resourcecache/file.xml"/>
-       
-        <bean id="otherFileResource" class="net.shibboleth.ext.spring.resource.FileBackedHTTPResource"
-              c:client-ref="shibboleth.FileCachingHttpClient" 
-              c:url="http://another.server.example.org/path/to/different/file.xml"
-              c:backingFile="/var/shibboleth/caches/resourcecache/differentFile.xml"/>
-              
-        In all cases you should review the "idp.httpclient.*" properties defined in services.properties
-    -->
-    
-    <!--
-    Otherwise by default we look at resources whose names are derived from %{idp.home}. Services not configured
-    using native Spring syntax also need to load the property-placeholder file in order to pull settings from
-    property sources.
-    -->
+    <!-- By default we look at resources whose names are derived from %{idp.home}. -->
 
-    <!-- This set of resources supports a native Spring relying-party.xml file. -->
     <util:list id="shibboleth.RelyingPartyResolverResources">
         <value>%{idp.home}/conf/relying-party.xml</value>
         <value>%{idp.home}/conf/credentials.xml</value>
-        <value>%{idp.home}/system/conf/relying-party-system.xml</value>
-    </util:list>
-
-    <!-- This set of resources supports a legacy 2.x relying-party.xml file. -->
-    <util:list id="shibboleth.LegacyRelyingPartyResolverResources">
-        <value>%{idp.home}/conf/relying-party.xml</value>
-        <value>%{idp.home}/system/conf/legacy-relying-party-defaults.xml</value>
     </util:list>
 
     <util:list id="shibboleth.MetadataResolverResources">
         <value>%{idp.home}/conf/metadata-providers.xml</value>
-        <value>%{idp.home}/system/conf/metadata-providers-system.xml</value>
     </util:list>
 
     <util:list id ="shibboleth.AttributeResolverResources">
         <value>%{idp.home}/conf/attribute-resolver.xml</value>
     </util:list>
 
+    <!--
+    This is suitable for new installs but will usually produce duplicate Attribute
+    output if a legacy resolver file is used that contains AttributeEncoders.
+    -->
+    <util:list id ="shibboleth.AttributeRegistryResources">
+        <value>%{idp.home}/conf/attribute-registry.xml</value>
+        <value>%{idp.home}/conf/attributes/default-rules.xml</value>
+        <value>%{idp.home}/conf/attribute-resolver.xml</value>
+    </util:list>
+
     <util:list id ="shibboleth.AttributeFilterResources">
         <value>%{idp.home}/conf/attribute-filter.xml</value>
     </util:list>
 
     <util:list id ="shibboleth.NameIdentifierGenerationResources">
         <value>%{idp.home}/conf/saml-nameid.xml</value>
-        <value>%{idp.home}/system/conf/saml-nameid-system.xml</value>
     </util:list>
     
     <util:list id="shibboleth.AccessControlResources">
         <value>%{idp.home}/conf/access-control.xml</value>
-        <value>%{idp.home}/system/conf/access-control-system.xml</value>
-    </util:list>
-
-    <util:list id="shibboleth.CASServiceRegistryResources">
-        <value>%{idp.home}/conf/cas-protocol.xml</value>
     </util:list>
 
     <!--
@@ -94,7 +53,6 @@
     -->
     <util:list id="shibboleth.MessageSourceResources">
         <value>%{idp.home}/messages/messages</value>
-        <value>%{idp.home}/system/messages/messages</value>
     </util:list>
     
 </beans>
diff --git a/conf/session-manager.xml b/conf/session-manager.xml
deleted file mode 100644
index 7372029..0000000
--- a/conf/session-manager.xml
+++ /dev/null
@@ -1,29 +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">
-
-    <!-- Flows that propagate logout to additional services using supported protocols. -->
-    <util:list id="shibboleth.LogoutPropagationFlows">
-        <ref bean="logoutprop/cas" />
-        <ref bean="logoutprop/saml2" />
-    </util:list>
-        
-    <!--
-    List of client-side storage service plugins. If you use server-side storage and don't need these
-    services, you can remove or comment out the <ref> elements, but don't remove the list bean or
-    a default list will be substituted for backward compatibility.
-    -->
-    <util:list id="shibboleth.ClientStorageServices">
-        <ref bean="shibboleth.ClientSessionStorageService" />
-        <ref bean="shibboleth.ClientPersistentStorageService" />
-    </util:list>
-    
-</beans>
diff --git a/credentials/idp-backchannel.crt b/credentials/idp-backchannel.crt
index fd26a59..a4d86af 100644
--- a/credentials/idp-backchannel.crt
+++ b/credentials/idp-backchannel.crt
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEKDCCApCgAwIBAgIVAJ0iknQBSFLEkl3ybj6HYSWkOw+CMA0GCSqGSIb3DQEB
-CwUAMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzAeFw0xOTEwMDIxNDQ2NTZa
-Fw0zOTEwMDIxNDQ2NTZaMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzCCAaIw
-DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJJI3OlyhXVII2YS2VGAZlCy/PE1
-RPLwTb9hIrBETcpA3JwVba2hBq8v0lWGpWkmvQfsjH+bKRJe611EyXwWQH04qGCU
-RDCFKBU8E9P87m6GTeh+DC6eVXxOB2h0pf3Zmktf48hlhV1X24NwIjba6v9X8oHF
-FTFFqopOPAaJWnODPQyul/d4DqkqkBfQer6p0RiDL/V79WpTVG87pJxmGH2FbchP
-PivVO9sMYfC5lqe37x/zu8huU0jDnB20eqEjnVNjvPjzbF36xPA06770FJuPxCYd
-5oebut50pO7DZY7MZGu4/UME0JfDrnCsyPz2L1gdxXX28mydAVL3YwIajZzuPVwJ
-HC+HJuF3YNgIZ7ZO6uN2Cyi1tKKAE5n3G19L8NLLW44MVxkS9ox9cFvw5e2Zm+ek
-Hh6iu6Y9/blyuFjlqVaffM6l6NVnAAXPiIpwnBdzWdJqMcJzgC5bTqOGEZdeR9hT
-ei0e1s+bmBj3/3cOB3hII74P5sCuGLfiYqSQzQIDAQABo2UwYzAdBgNVHQ4EFgQU
-hb0zxPkLe5m7vmD8AH0fjATSaIwwQgYDVR0RBDswOYIPaWRwLmV4YW1wbGUub3Jn
-hiZodHRwczovL2lkcC5leGFtcGxlLm9yZy9pZHAvc2hpYmJvbGV0aDANBgkqhkiG
-9w0BAQsFAAOCAYEADQ17KGVQJ6AZTqDUDxVAfrTlFXysuvQg1WntrMB1PUzlb6Pa
-AO6Nb24YiY0PonSk7iz+gOg4P/V2b9wX4NXPBcX5h86fxR8R3cwZYsYKhwBBQ6uo
-UZnqtNyYNY/3hM2Dj8sR1PMijwgNmo7KOzzBPKKhID2dtGL3bS3TrX8xjmc7NK+r
-5VE9LrK3kG3ht3qM0I7iPMNuQXBOuduRG8WGD8NsFwHcYfORJmK5Ac/AtjHMVLF0
-x+m4LyLxP53t9/5+5fiJ3bghXM7Uuzjjmes6fdZyUcxinrwFxvSIGz3gqXf35Omf
-EwFemewB5B9GkAVXJSq2J64+iWXTo556YEC/RUrX6ZA5db6zHIeHX4BSf7U5YUBm
-LRJ/RJZKKPKEBBJgvh8vUFLF64tDn0c9x3n1mw+ZLHnPcjdX5v/stLVgR020vRx7
-8CGsrydmj+80Gm3Ji1eGJfD2LdUslve3bNerEW2AUM3DFx6wDlR5K/0ix98Ah1w0
-AuAeyajXyLR9NkPm
+MIIEJzCCAo+gAwIBAgIUEtJU0oOkMid5473At++VFGAbX3gwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTIxMDMyNDE1NTQyNFoX
+DTQxMDMyNDE1NTQyNFowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
+BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAq+6x7Ay8s9vl/r+trvJMbwdXiFxH
+PwQeJ/Oof48EWuP61zluBENhk9E5rdf2zlCxkfiB78G8YFZh9ZjcWkIR63xIO9YA
++NuQg+WOPu8fvegcly0ulg2dRXvi0b7q/FsK1MtKcxRECpTNu2DD6K5oHkjf/nmp
+nJIlAxvYyP0aqwEy+qq1NFC+WTjoFP7ZyKt+oSz08ONV2v/1dNRwcjfgc8MJcoq0
+Nw56mGZ2LlTidXP8lQBpsQ6/gJvdnVv/B4q8fVS3zpFgokkyQM6eW1ZpGjPY9K1A
+paLcAio+MCoPbRJwAlI+5tdgKMMvz+xq4RN0e68IIZS4IgmkVem52uJcfUiX297F
+Ar1QdH4NZvijir2Wt4xYMxpThsV6n7F88wWzJj/D5bErZeIWG+DWJq2FZ7rqq3Oc
+tz22TH3iBkYrSvFG5nwyHQJaptDDMm6OpWTfmcjh9jT9H6mz4BdBln2uJUswVNGG
+bR9w9OcXqYN6X8bll9Q9XcVZh2uBgPB3NWGzAgMBAAGjZTBjMB0GA1UdDgQWBBTc
+BIECuv3b1y5K9FBK2zKFc2j4HzBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
+Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
+DQEBCwUAA4IBgQAQsx5PLHRi8+WjBTSW6RiNiSRFTpNKPdFzoKDhpaCVSlrpjgzp
+0qD7QorlKPVJNUhl56Fs2S6oWy6e7lb1eBPBAfCNqTalFJNnDdMvZh02FCecbE87
+6Wv7JcD5kA+f6HUDwmaB15fabheSE3YMGQFtaEidmd/jd23CaDL5RNeHUoKS6JHC
+yNsUlZ+R0Cq2ia2wLhW2Z2CYpNh9JM/LOmcTslOgmThNeCnrMIikWSTLQ4C3H9/R
+/iN8NaQhKn4vcYTwEqiaVFQbIU2mQQLT+YK63L4S4S339IsjZiqGEw8DKBnfjL7b
+D1snXa+G6MiQJNcuChuvGfGSlXCSFjtUr9vivzHeGW2h+6uStzTuZ7t5NhQMRTFD
+qT+gyCR/bzsEUh1Lj3J2mFPM/cUSlhH3H0TJcVT9GZUzFNAP0qbaFs9PxXH2gpDI
+XrshYcEiXlj+dsSUNhaCqYibPwkHrRBIAqoDGdMFI+Y5SePVo4ksA55m0gPeY+FM
+mUbCNQngUzNlYPU=
 -----END CERTIFICATE-----
diff --git a/credentials/idp-backchannel.p12 b/credentials/idp-backchannel.p12
index ef5ab52..9e30c3d 100644
Binary files a/credentials/idp-backchannel.p12 and b/credentials/idp-backchannel.p12 differ
diff --git a/credentials/idp-encryption.crt b/credentials/idp-encryption.crt
index 23bbeb8..10fa34d 100644
--- a/credentials/idp-encryption.crt
+++ b/credentials/idp-encryption.crt
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEJzCCAo+gAwIBAgIUe0fsxBFnYrItqaF1zUSc7oTFFhswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NloX
-DTM5MTAwMjE0NDY1NlowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAlBwK5LM+22M0RLLhaVoTlgGJlF75
-0hfDGl45GqSVh7gB4X93icnoh2mUoGq/wgqx+YwCJ04hEJF0BXGRzmP5qQdSPw/z
-VV2e90emvoFvRD0OWrRDo4kn9GO2a4t8nAdLNe8dclsEpxyKktvmppMbna0jNGau
-h8OMsSNlTKH8C6qzIUtxOGnN75Qw1JAQ0N6U0Jl9w7x1LoR2tiyiTDKMAyx8v7xu
-eurxduh/Y1g/2fxi3UGA0i0znwTjEM0eZ/3JQMtuCKW6mTNTF/klBWiEhP6Vm3Yk
-WgbYDMgahiaEo2dzxmKgFfFysoSxkfV93zSh31+zKovj5NpNEU9LrlFDD8iRYPlK
-ZKjdleWOsGFbtyfvSV8Xq1bJvn9LScH02gCDbjkYFOlGgs32nGIqe4tr7ekT8A60
-S9dtIV54834ZdntBRzPkaLRaHb6FWY74U5+o1U1spd2JhWvFMlrkHCghcIWKmG87
-pzmZBFcyxSBIK0E6dhjm3EGXMmWdn80Sr1lxAgMBAAGjZTBjMB0GA1UdDgQWBBQ8
-+tUYkLiwLXUxRdIcfwUUs3s+dTBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
-Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQBXnSl1RPlziZEpGUc3FGoQCpsu6FovK7jlieATyKWD3NY7lha6
-iOqiyxpNnrekh3Sf3XvmwvoxBHULQNS06GMMej8WtFBSaomNIkuztzMUAEmil2UF
-rP1xT0Gx+lT/Don9e60dGMMl2FWYIHobkQj4yhjSW6yN/emQRkwOhkj1DRGkZ1Zz
-wIRtH7/VT1YXH6n4P6lWNMgV+GInhT7ogitN5Vf6tCfMaZtowu3bb2I1gDlgYY/v
-0TrokTQteO7vcf+EpTODPRBiFV/Wwub5r8BDN4O3qGt52f2lhlEqdupFArooNVyF
-tU+zmj0gaclvvBBAaN2oh0Tj+j7HBh1YWB8p93vm62dKqY/9L9xSNAni6EI5o7dm
-58OUngvQopb7U7MDDuH2gM0XiH/R2BNp4c7/jqBP2Of5Bg68yKCZHB7D5XOJbQLf
-gjm4h9tRHtDijVkHcuIEICBwrie+JSEL225UnTfsesPiArDvo5BhQeNc3q1CPJgF
-2QOuaDoiGwFbc5s=
+MIIEKDCCApCgAwIBAgIVAPyKe4kuv7ZzU9YkyhDT6PWudYj5MA0GCSqGSIb3DQEB
+CwUAMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzAeFw0yMTAzMjQxNTU0MjNa
+Fw00MTAzMjQxNTU0MjNaMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzCCAaIw
+DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAL+i5PmO/JsPcM25CSY0zJeJ+rim
+4mqlr0sT7BRIEEv6ja9RAxRI3fRXOYfz6PxfF6AMsYy35bCueOAOcbr5IyCIhHiu
+HemT3ieiROoOUY3P0D4KdwC3cSxANc53pEIVsNd05Xxe2mVnGJ9liomWGl0Zsj4v
+TC6f7PFjAEV3JyaETMyLpKVH9rt9FVKPZ3zl9FN/nqA0KodjQVbJYjIyJsib3WBB
+WWZ6VgwErHQriCk2gIGrYbltcZe3ujKOpNaRiIraG1VPs/YaP0IcsPekS0Vy9qcF
+6Xq4xErWdR+Fh0v5iI6bZ3feKnGDO1q30M5I/cfkwW9CQd9zqLjM38MilFJYCoqI
+KbZRPvvKAt1B/JZJMhZZJaBy9y5CtTHnZiEZxdovz1R8BsZgmYgMRfIqTAN3+bYl
+kzfgaS/PmQkiY+iUzsi7Bi753Eqlaksa1xqeV7tkpVRDOUeTMOvjBzueQS1wdP7i
+VgiQrWF+EqBBxGY6QqlYdPbOZOwcL8nOE6+BwwIDAQABo2UwYzAdBgNVHQ4EFgQU
+N1YcXFUpP/ioF9ByIell/FLIxCIwQgYDVR0RBDswOYIPaWRwLmV4YW1wbGUub3Jn
+hiZodHRwczovL2lkcC5leGFtcGxlLm9yZy9pZHAvc2hpYmJvbGV0aDANBgkqhkiG
+9w0BAQsFAAOCAYEAq3MFr90wgCFV2fUdxACwnytfK3tlpT7bczA4ks3iUlMM2o8t
+QuaMe5pru+5nhMk+D8Be3RoIIks/ddxHwVKbwLjzJFEG/9S43MduXP6P3weMr0Y8
+lIqZrd65uaaEbAd0ldGSn6ekB+ERwDNC2aYghwMIPqyCvQo6vLRsBsnLEa3q63Xr
+GYbkCawtvMTINYxAgFP0vavxNXF7A9qqDCpS/m4QgdbL7DLEJTN/wCgJVPTA9f9M
+SyjcmSRJ2FMNHyRgor26jT0rCeUNJ1MgM0kA3hwqW5eK+nj9OZWWVjOZaAkdVRn1
+mGJoRmtK/dGE4SEXfyIgWqQfdGOpIAEkIG9EHaH37Kg+slMjb/ZwN/riShIxPacT
+YPkAC/AqRaiJOzvi4ZB9OtjC3wyoyak5e33p5DnCIQ2+hEbebAsnYWP6Yf/c1KMw
+1Z56FlQwmY1yBZ6+yTIR0jCKWj5mFuahsDW7VSkRUBmt55Q/o24YbHfLioYRSJAi
+uADV9N9NCGawgJnf
 -----END CERTIFICATE-----
diff --git a/credentials/idp-encryption.key b/credentials/idp-encryption.key
index 3e9f81c..b8ed07c 100644
--- a/credentials/idp-encryption.key
+++ b/credentials/idp-encryption.key
@@ -1,39 +1,39 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIG4wIBAAKCAYEAlBwK5LM+22M0RLLhaVoTlgGJlF750hfDGl45GqSVh7gB4X93
-icnoh2mUoGq/wgqx+YwCJ04hEJF0BXGRzmP5qQdSPw/zVV2e90emvoFvRD0OWrRD
-o4kn9GO2a4t8nAdLNe8dclsEpxyKktvmppMbna0jNGauh8OMsSNlTKH8C6qzIUtx
-OGnN75Qw1JAQ0N6U0Jl9w7x1LoR2tiyiTDKMAyx8v7xueurxduh/Y1g/2fxi3UGA
-0i0znwTjEM0eZ/3JQMtuCKW6mTNTF/klBWiEhP6Vm3YkWgbYDMgahiaEo2dzxmKg
-FfFysoSxkfV93zSh31+zKovj5NpNEU9LrlFDD8iRYPlKZKjdleWOsGFbtyfvSV8X
-q1bJvn9LScH02gCDbjkYFOlGgs32nGIqe4tr7ekT8A60S9dtIV54834ZdntBRzPk
-aLRaHb6FWY74U5+o1U1spd2JhWvFMlrkHCghcIWKmG87pzmZBFcyxSBIK0E6dhjm
-3EGXMmWdn80Sr1lxAgMBAAECggGAOEnMDgzdR62VMMK3Dj3wkaL18ZCC60iimoPS
-ugBw38qb1GKIQLKej9AdbzYCuLEt4IRIUT3NLSnKaUM3QbQXLxkcNeFO/lN9VcdC
-ZMZ2Tf3SVcCKsD0xFR1MN+UkL3xKJi5BB7P1ubkMJTIzn3zrEuq5JXIcxHYaIzwr
-hItPafOu7mlolyMG5BVy1WYHLgpZjkm3VUtrUYmAQE4IRGM1eQNQSeJILqjZqfJE
-b7IbWjIkNKhvV/Fb3ASUc08xTh5R5daoC3JrdtcCUb77Og4Gn7UBht7miyBx78EW
-8kuy11kbZB7IO3h1DJkfsW7pwHkkrXFL7mmg8qS4sAMcIATom2oysgriYAGxaBZp
-Ub2lZlTj/pPoUuqG5bixedQozirV/m0bIPzFUP+2JDlqZJSkBV2f8VkTwKi4udk/
-fYiWM4POqaWD19DMcwZ3mMRYdmMXN1hYam3VRwFHt8xsToO31l1lI6/ndWNet1BG
-izrergy8vh3X9I2iL/MtfUXurKx9AoHBAPDDPf4U7mjU2SxlUtGXBjZQU/CIa7YE
-y1jXMuRKIpzCcOpIEqIIVD0Mbl7a7pGxuXIRjrvxgLVtTCN2c3jZlHkUxWfJ867g
-gaCYwqNz7PZBr5ChQl+UsEzrM2tE+Vd512HQW8Zu1XfoXdoEPkQTAQEy/21jERAu
-sVIzclkwUoAYVBn8Yi8V6TZvJiKobU2t+5N0ngiyOYa6FTsHG36yrzryEUdQjj5q
-QfPtZtCVe8k6gH8GzqL92h6HmKWbtGQgYwKBwQCde6oycL2fPEoJVG99aGwbenOp
-jAMYjZN1cvf7IYiRoJ1hY90TXs9I+Th0ASuuoaiqQWS5s0xVfU/ROWg8hz9AY0Fh
-EkR/iI7WdPXR1pfLc8Gc+IM8fx44cixL/wwIrmfz1TTUA58+36Topcgj3pO/7sBK
-dWX6O7f9e2iL2hFLKUYmkKLylFW1iy9TZHWYiW3A+P2eXoLqOXH067SFkmgVmRyI
-zo6aP/+ui0Ob+GqrJtE0qYCoIT9bx8M2aJ/qBRsCgcBv14K4wShu8lFgWkE6s5lj
-KbWUiwreJyP/RRiTDA1AHOMvMgPV2WCoa1nqHnGspI6s+pL/o5RSs08nOiMyBIEA
-LjH1oM7ecdRFsjDYlUWCr8jKut6GYB/121yrfAMIK8Vt3siDSYFIjlzqpgX2wY05
-7WLSga6vgcFFmjiITfZFIwgOejtx/A+2BbQFbZA5AZVYTlgLWh93AoJSRV70YDUe
-gMyeAEHTpLC2i5WzV32FYPPIDnV3Kc1lWUADzmziBlkCgcEAk3tfrbM1ce2lLE2d
-x6VGMQmhTfPoZlMX+JL9t3r1CeSP3sgGHwDYQO/ctY7vGLEeYquxJ9PJNfqQCFGp
-052ZV7RcYwsXiRQbKK4KFETSjV9Pv7BgPwSRCa2q3FTzMSIcChbuTWtC9D+/kXzI
-DQeB+OofvNtq8EiDC2lKREapkWkK4EztvR27krPRU1iuZHa3iVPlOC4sjivUE9m1
-iq3MugVU2q4OkFhFG3Iik+u2AajtnVLsQQg57LsMj2S19hRnAoHAdzabeYxnCZDX
-AHPwMTZyBltOApLU3yy1TqPSunDHHl+AN/56Ct5Ug2d1pLYgGvk5oIrz1j8txEki
-aGfjhIs26lfjOJ2y4HIbLdeNDvfWLHi7OreqNkN2Yq9UULvDSW5ASngom760o2Hn
-e/VPvoWQgvIFCrhw7jBC0GJFHVFwBpjs4kjUgmr8jbxkWgk3LC/SugclDZUnE4X2
-ecB5GgbcER+qYbt7WuDYf3690QTp3n+h7BXs9UTeJXIV9BzY1JqN
+MIIG5QIBAAKCAYEAv6Lk+Y78mw9wzbkJJjTMl4n6uKbiaqWvSxPsFEgQS/qNr1ED
+FEjd9Fc5h/Po/F8XoAyxjLflsK544A5xuvkjIIiEeK4d6ZPeJ6JE6g5Rjc/QPgp3
+ALdxLEA1znekQhWw13TlfF7aZWcYn2WKiZYaXRmyPi9MLp/s8WMARXcnJoRMzIuk
+pUf2u30VUo9nfOX0U3+eoDQqh2NBVsliMjImyJvdYEFZZnpWDASsdCuIKTaAgath
+uW1xl7e6Mo6k1pGIitobVU+z9ho/Qhyw96RLRXL2pwXperjEStZ1H4WHS/mIjptn
+d94qcYM7WrfQzkj9x+TBb0JB33OouMzfwyKUUlgKiogptlE++8oC3UH8lkkyFlkl
+oHL3LkK1MedmIRnF2i/PVHwGxmCZiAxF8ipMA3f5tiWTN+BpL8+ZCSJj6JTOyLsG
+LvncSqVqSxrXGp5Xu2SlVEM5R5Mw6+MHO55BLXB0/uJWCJCtYX4SoEHEZjpCqVh0
+9s5k7Bwvyc4Tr4HDAgMBAAECggGBAIQTUJxu38o+qhAfJx8d5KPMhPAelI3MAzRL
+VrnjsNesp1ndC7I/RjnQo+X/ROQq5a15EiVZ2QQcO1KwodGrQ3p4nFRQLG1/a+0E
++VoW5D5Iq80WiU4FIArPdkYGTz78lBTqi/9boEmi9GVnJkQNH75qp14UWv0HW9ZB
+1T4LEQCKziNrWt5O6s3tN3TfQQPjuLCTlE/1pBoLXkziHrtZtUEtqzVb1LG8PvGp
+hvHJzt4Yohi8dW3G8DMQfVO63ADF65OwjaMO4SmU/lbRDqJSvb4LxRiahRasBLYC
+qoqi53Y3grDiZMVd6XAnDrr12JzsgGDj2/j4GiMHSQKkPBMcy+SQpiVYV2jFiaGn
+31vJufShqP+70Vez+1DVwjj9Gf/R/3zipib9q8sz7UDkpi2Du5I2mX4K5uEmx9Aw
+hkZoqIM+yHegfDSIwCqHqNqh7mHOwHOmOAgFqkY2DNyTpA513iIUzggQ1pNKsg+d
+cLljbubz7KppNApcTBaZUSGy7KzFAQKBwQDnKoxT1feWZhsDPOFa474sebHfpsMK
+vlvnEUzG4UvBz/QqR8ib7BsT2ZuF90lo+NTDg6Wohn5J/gTc6z0J5SBhjDay21a4
+qaGTA2BZL6D1el3yBTI0dK9AA/1UaNGQN1MUNmHEXlxFuAh6KEEbau0qNNgxJXpQ
+90FzQaonHdstGRj49iHbX1xO28AYlRkYFzraR9u1M8wFcWnVpoJ8nHP3LH/Qwq3m
+8ov63Jl9YkxPgvOnZb3Irj3Pz20CIgBWUPkCgcEA1Dk1ewLqkxYgMEcRnGGyF489
+3K88pe28/HCL7qWUuIHyHHnym10S0qRHxApTPKhpJS7L/h46lqFfPuxvLHLfB8I+
+uXxq4TKHVRbLHxbcC6h7oHJS5Ezi+PCIFP8nINJ97wq7OWaPVn388MU8sA9khy5j
+gsyPoRj8QnJrWi37j6RFJWoYiCwFRRtCzhMRJUafuOba865h2wXUZwhfMPCuhA4u
+go5621Sld/RD9PajGsfiGx/5uMdtdvPwDzLXOhObAoHBANUKI1VIBes3ooFzZASN
+isAWT1VcrLeEA9KJ4QYQr+6oJc+pZDo+eB3tGCV4ZtE1MXAWLV+Iw26Rig3HRfOO
+lC8SN37SIbQBsQR5whuvh1l0MoxPOZuaRcBrbNaT2z5bnlcsXyHIDKW8GyPpYUdR
+Xczd8rgoX/eqR0lfJN7z5wBC9v7KZx1zXvDWGM0O65eGIRj1zIfMeqQxh2X9FJie
+30jWW90a7YW/1j2VfGdPZiCJAOAvJZ6C5jhUY5PpngHukQKBwQCk7Qy920dXJWPA
+gQqToGzZ2Ez4Gwsj3Dz5ZbGpte588Sepr6+1w8AkCN1o4alMQ4jrB5Iqm21msGQn
+r3C6d08SZYd/eMxK1IzNuJgEQiyhtr7UsuPuXj4pvivTPXM4E70grxNPCYAtdF3E
+81M1c9DpKUjWVojsZlFshiUdgQy11bCS4f/Mm4FA8m2ZXsH9WQQ5mtbfd06++qnV
+pHDtxK2rHKZSec3Kc97f+OlzDtU0s8/oypG0Yu+T+QE/noAaty8CgcBLiCGm3D4z
+eQvCyp2ifIx3aS0EPClKYME3x5TyZJbQ5EKYEsmWk5zpfNczwQCSjgnURs1X4Txv
+4vTShW6isvC4D1+nmK19jajlhk9humMshhLSkSsbWAMIJYtqwz/w6CN4b7QvXhcB
+x7d3BR8cL8/aLAJxBLx0hcenbEM6u8f3nAivllcrW0kMrJDErjT8unkQJdLWV3ct
+qvrSqBArpykBjayM52USIUuNZFUIvjmwN2XUlC46+388fWwIiPwnfM0=
 -----END RSA PRIVATE KEY-----
diff --git a/credentials/idp-signing.crt b/credentials/idp-signing.crt
index 0468315..a7f2528 100644
--- a/credentials/idp-signing.crt
+++ b/credentials/idp-signing.crt
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEJzCCAo+gAwIBAgIUOCYqGG6JElEG1wHKL7CvULRTvEswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NVoX
-DTM5MTAwMjE0NDY1NVowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwkiDw0dpZmup6VpfVXkib8fiv7KF
-T1Z3z6tq7c/ki/CH2x8BYtLPNgIvQa8KhggHUKG+rRU9yBwWg4Yvdsi05h5pJwcE
-xE1hwE7oVWiY+DtMggv4zVbDm0TnbvJvXN9eYXNn/e9RL3hD3umPIzDSli3wwiNg
-GvMesn/4Npq6ERi80CPIkUENkL3N7XTDX+Fy/mhXCxc73Dv3Meo0qk0pii005nV1
-vHCP9jsUgPfDCBScUuikfQ8V9SPLgOSf1x3vc5RqSPWaHgLesqoXpFFTthlVjB8j
-cUzqjQllhOS6LKWJE7VIfV6MdpfkRZBWhsaeuT7I48kRmFuALLnIopkclqu3HtON
-0Fgd1oPPBHa04bLcPqbneqGL+2RzZOdnuarTtY+JOuCRnE1qCWUeRoH2yeMMdKPy
-amX6HZJ35Vsk3uJxJX/IyipduZ+nHPC5qi52Elu+oyBrJwTbVAhhlXwPehC6nU/c
-1LUnbo3M4SGOYWuPmI1ko5KF91MVUU7ttmkFAgMBAAGjZTBjMB0GA1UdDgQWBBQ1
-CuX1jKcG8rdC0xBBveSJAYoFfzBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
+MIIEJzCCAo+gAwIBAgIUZMvUeW53jFMs4M1rlNztvoKNXGowDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTIxMDMyNDE1NTQyMloX
+DTQxMDMyNDE1NTQyMlowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
+BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvtENeKgTFxJ3l8ZTeaFifLRLS4da
+xjnKy7JpTfrVOqZHGUQ3zAwY4xifs5rbiBkOAiLLBIqjJJalZQ6A+fSu34eVYdxp
+5VY5L2gAcF/6kf+wOMCU2zdEwiewM9CZMo6HN77Z/ZEC1737/OBaRHwCEtC8l1Bx
+U0V9TgEB/n31mtg5h7FWDPe6dgo1NSeCjsKVGHrdG4Ozo+JHvklqy6knbqnNvPqm
+cLv4nrp/wQnRalqv7/26dlzoecXmCICH4cToBVACILXs331bpWEdHEc+bxInja15
+BOwb4pWLbqD5Qaj9hnPFCAKFtA+Ivb9PKV+44eNN3n73dYEPmx21QeqXWVfn3Ukl
+4lIIhFC9XETbmSI+V8HLYl7e7n6GKN3hdVip0thN5vyPWYBt2DskW6+QFXry2F+E
+qMxNHUqJt0k3uu4pTZ9f/DsQaA+/e+H23DGBIOytNzBz1jbU0Do/35td39YvRGN4
+T5KOuwmGTjrB6cM0/WOxJhaKourpM6qiDs0bAgMBAAGjZTBjMB0GA1UdDgQWBBSA
+UDgNLBosYiGapWvY1CIRGm5f/jBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
 Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQA89rYZmayIfst0cGyt+zdeHpnvyo+zVfAk7OztXF5OXsakX9TV
-Iq8ur1lq4Q4KC/Ev+9p1za1gP7Ea9ugFJinuVa6ntpzGP0vh42pmphLNaRFvnPch
-pwgGCvcF2leYG6zZl/Qln0Kbv+pyByens7xPdKKA8U5ySVkouLuw7017XSIulPtW
-u5tPz51awJubHCK+FckcVH0yZZg44s4HmjzLpJCdslMIxmhtX7DW3vtqH1pL9Mir
-3qykySFUJGthV3ndHesG08y3Tni5HZaRqHHafGRBiezO8JCwVvWrdC29SdAwY2i0
-HhKB7zCDOpYrh3o8TTx3ZJd+6Uel/e0bCefs9uhMj7O5ErNySHyTtNRrFxTl2c98
-RDweMp6NLfm+P3+EqJycmpR9CKudcL6RUikN9hDvy6qqG2t5fW7pvU/+mzRm/3Cf
-gMxKHQM+OAry1E6pQSYh8qkPZYDezwiz4gINxn7SFAxFJQcTlaSVmFHLOQV7TetI
-g4sTktRrBmgU/vk=
+DQEBCwUAA4IBgQBb9ncPd748rnxrJ7tat50vDGAj/wnFM/9qt6gfwSv7gCikj29V
+QYgZ0gB76xH7RdLw/iuR4g3stuoARt+CYrzkh/A/pG6/FAFI6HZvX/Lic7YLv/rp
+m0aRcBLDzu6gYZ66qm05iXLs1Kueq8Eh0txpbg35LUVZGtXxE6t4da8a/XfSfgDs
+KlUj7ANT1vkbDYXJiio60EqGWxMiyxTacEFOSUqRTlDL1wdvU8hrcyO4ZQSf20Mv
+uROvXwki8Zb1Hoakn51fgJIKvIM6ttLpNdwsXFWpopMw9s5obtrNAB4KbbuISXdn
+3AjJtynK9HuIOyBkphetJcOXj99bAn6VLyl3ieuPPLzXPQ9byNmLlwp0njJE2xtR
+HjztBijmO8wtif3di+nUSwHRG0DcuE7f06Z28+pSrpB0XHDmALSefbq5g51aIR64
+fgC3txaEwILjHFjdK7Iaf0DHqQDUyxqC00IWATB9Dr9dtMIeQVN46x4681AfKp8p
+oHdTCGNvbFo8vGI=
 -----END CERTIFICATE-----
diff --git a/credentials/idp-signing.key b/credentials/idp-signing.key
index 9fe1261..cf8eb60 100644
--- a/credentials/idp-signing.key
+++ b/credentials/idp-signing.key
@@ -1,39 +1,39 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIG4wIBAAKCAYEAwkiDw0dpZmup6VpfVXkib8fiv7KFT1Z3z6tq7c/ki/CH2x8B
-YtLPNgIvQa8KhggHUKG+rRU9yBwWg4Yvdsi05h5pJwcExE1hwE7oVWiY+DtMggv4
-zVbDm0TnbvJvXN9eYXNn/e9RL3hD3umPIzDSli3wwiNgGvMesn/4Npq6ERi80CPI
-kUENkL3N7XTDX+Fy/mhXCxc73Dv3Meo0qk0pii005nV1vHCP9jsUgPfDCBScUuik
-fQ8V9SPLgOSf1x3vc5RqSPWaHgLesqoXpFFTthlVjB8jcUzqjQllhOS6LKWJE7VI
-fV6MdpfkRZBWhsaeuT7I48kRmFuALLnIopkclqu3HtON0Fgd1oPPBHa04bLcPqbn
-eqGL+2RzZOdnuarTtY+JOuCRnE1qCWUeRoH2yeMMdKPyamX6HZJ35Vsk3uJxJX/I
-yipduZ+nHPC5qi52Elu+oyBrJwTbVAhhlXwPehC6nU/c1LUnbo3M4SGOYWuPmI1k
-o5KF91MVUU7ttmkFAgMBAAECggGBAKiX0reX9a/qR9T3FnmOl8KWm38shKCXcXrl
-zvG1kSeav9n3avV96FB+ztFZ+3DZ8LcY1OVP5IANV8AkpnWWr9xtkWRLo+hRGj2O
-e/D5xpzKoJbNmsddvnqz7X2Kpfba4wT/58MldLcTzxnWZd7s1CF8lktx9UkNpprR
-j+yaklKZu+eG1dqur/3lp5ii1ZQTiP2aP8ahD9IKu3U2PyN1uFFu71P5pAS1TUgo
-dp9/4V/Wutz7gxn/CFflCwi73LUJBKfeJM4XaBccXkZhwNBQDvFUrBKZXIo6M7LZ
-XlOGS8d8E6EZgFFl4NhJpWk3ckKNIi7AlK5zhra6i5+JgpWrVYrWNk9tzsuL9b+0
-mia4is3XYo3l8nqnyZLNcvE+OKmci9Z/BMxDZ82tiFWSSjqrAnoDZR/oI9L6niOU
-0vk6UtFW1BqK8vUN0DrD6pOYKmsALwPx9JmnGnGS8vBOZZRKX2YjkOY7pFXGi+YH
-CZ5MTc8lyHJngyN8EgJ1T50kc4HjQQKBwQD1VhTmnRg6EwrtIGhXLSwY+dRL5WK+
-qaovpXcyMj6F2r+Dl/QBq+QD7uP3U5vI+kEa2JdBd9OOaxBXdXZK1/9zk+jfEUtT
-SvWCcKoB/Xrla4WHfGEtUxC7qitkfTy57PB5j1X5qDr87epZ15mRAz7r7F64XjwT
-pbuZT5wHAZnrphVs4TjBh2QjTP8ATj01J508XI6DC7KMxdYioApD1Kv5VV73fiNi
-cpS9NLtkaR646peZ77tYa+7pgcVcxmcj8lUCgcEAyrpafyiI9IyrFsZWAacvb3r+
-jRJh+fNF/u/VixDMwAFVwjy8CMIC4EbDfyHalsPHN8yr0NogCSZ5iao9/benx6gm
-4i/3mxhOY68h/N28etJU55cPoOIWGXcs4KJNEQNC7N78yU95sC4IXJyFwzI76VWx
-pCzPx8QYzYo1Uy/rALuMXJ6FFhZ/fPqwQKtxpNxO/jVGSHXA0Ibn1ED3vMBzD9vp
-fP0si69AjYfLaqk/dsq/rljIXxBmfYX3oYJHfyvxAoHAe8/PiHqraVOG5hi+z4/6
-ezhJjWvcI4CYZKdKukhlCURV9mFPQTCwR9PdtEm7ivfQt22rF90TJQKfIqQi6K6N
-OpTgpwKhUw23TPbytUJpLTLQFooMuMT84tiEQZh6dxI+YfqWVwIxkse2x1RpKafL
-r2CAhOb5xqiTPlHQ2jBSr3wHwAUBkZl0TeRjpJHXjeXKElZbjYLvvt9wq9S8mXLQ
-v2n4HUrJLLvKmJnuIER0vrmVfJhhocQGtE1LfwCZuKhpAoHAULbjgw8zgBJlp/qt
-kZjr5PnWUXqJMcgvDTKWFflJXATsDRq7Ts1X8c2a1oo3CqHGNqwxmETQTnRYHXx/
-k/3EOlTzrkikz8Zcp4m6AYCTI1+M2Gwnl8mMPPVbE9Dq2CQxSDf783bGH2QkhiL3
-iuD8Q4mP4arJy2KC8YreclF4wmDpoJKosEOi3LK+6/CWnantdX7mjcD8VMnxkWuQ
-d0E0TpMjIlV2n+LV08PGNKBQGU7eBF9q35abB80H6/D/4F0xAoHAea5EbTEhTd91
-c82Kus2Mo5NY1oN5V5gxjrp9MHqB9AQfo/Ihks/VLV+2TFDIncFgdQvdzWm1QTNj
-PPLMRcxkVDjqjjlE7ymPGVLHZIDRRuDosATqOD9j+JHSib008xJVdL5awm8yG32T
-zQz+o+rjD+b64KhWamVuKUaf0DXE9i9hIjeROlzw5c+TD4yo8RLRRxNekX8tfxZ7
-nIapUVjyooDHQ8UfdOqpBfWXprrNrwSVQOROCeQFmongU9ZIaYAo
+MIIG4gIBAAKCAYEAvtENeKgTFxJ3l8ZTeaFifLRLS4daxjnKy7JpTfrVOqZHGUQ3
+zAwY4xifs5rbiBkOAiLLBIqjJJalZQ6A+fSu34eVYdxp5VY5L2gAcF/6kf+wOMCU
+2zdEwiewM9CZMo6HN77Z/ZEC1737/OBaRHwCEtC8l1BxU0V9TgEB/n31mtg5h7FW
+DPe6dgo1NSeCjsKVGHrdG4Ozo+JHvklqy6knbqnNvPqmcLv4nrp/wQnRalqv7/26
+dlzoecXmCICH4cToBVACILXs331bpWEdHEc+bxInja15BOwb4pWLbqD5Qaj9hnPF
+CAKFtA+Ivb9PKV+44eNN3n73dYEPmx21QeqXWVfn3Ukl4lIIhFC9XETbmSI+V8HL
+Yl7e7n6GKN3hdVip0thN5vyPWYBt2DskW6+QFXry2F+EqMxNHUqJt0k3uu4pTZ9f
+/DsQaA+/e+H23DGBIOytNzBz1jbU0Do/35td39YvRGN4T5KOuwmGTjrB6cM0/WOx
+JhaKourpM6qiDs0bAgMBAAECggGAXXk7CCgNcffx7b+RlLuh60TGvbEInqIg3bgA
+Ldr6KUja+12Xl7U1W8nsMadic0ESw6kXmpnvYTUKwH5iYA+kuotIei/nEBk02iww
+Stw5etuuD58HTHu+iv22Kyu8YC/BvWUYlEY9BkJi9nVQwsucmGr4d4dIfGpF/7gu
+qeQ6NChHxljwtlmEVd6aQfeg1R4su1k0hw31Kgrm6ig80JeEYYl8515BumfaWqcx
+ffa5R0g1d3LrrJ/GoiB3lyKfbdFuns5Nw6Cd4gBwTFoFwZrRPGXQGnBNLhaicSFQ
+vchLZQDe+SCdfOcdCmYI7pm9i8jbI+deTzDCT1am3gqvoil0Y+TW9EDk20a4vVnH
+unSsz+kIpVw1O8Hkc7U4yPXxLbS8qTMJUmp0GwLV9egGy8iVVjPXp8VbyjiEDNIJ
+Sp8y9wvjvDPDPxPg7H9Jkgk41muBVuo4KfpaojXSRomlqSD8NfzL6TIMSCPFq2vO
+brp3Gblf14jwj1gPaHiQ7Kr1cH/BAoHBAOLoUvcS1kbxp0NDDBiEgCLPXpoG8MMc
+Y3iSAZ9dtDXyqaUiFEyrpOCtJdIo/YW+on7J86t/+2t5hhJ1VQq7jUpHvoCnIOEj
+SuMAv806owV7XueoFBpaKBEMp28gWFAygeKhGI9g75hjq23f55XT43jPB4NOmYmW
+/Qle2ZS3G/lWKfMbNPbk4MAvvCULVWjaXgzOKnU3L4LybXYq1KzW0xxI7bAEj5ft
+38SyzCJn0pIhpvDgQe0TpkBGajDeHEQiNQKBwQDXSCJbWC8B8dF/kjdTPeeDo/gX
+sK2nBRxQuNJ6BwpAHaPcOA6G3Xcb9LNDFuRReh5jFDs1G86N4ZhL2dVthsQJHt/9
+1pNrn7/UlOjrgRKVZDR8gFZxvuxn/TifuR3xv6+kTgaqknMepA5SpD4VB55VBeJP
+B5OJtSrHxHh4fty+OMvvmpBNC+505yxY69nIRxAtOaFH6xFyM/klp7jgKsJV4lco
+Un1WO0BqflPkLXlbMx4FjcSjikUnkhzbJxdnHA8CgcARfOxgBIClSRymD3XQMe4a
+QLc+0cgekYKNGVusp7Eq8z/l7UF5Q0Va151xnB0mALJPaUsxbZS4DM6rf4WFZT0X
+e34QNlFPaMPtyPH/ZESKOJ7w5cBe45Hw9nO1Gd4UmD/wcpANBOCScyQUPMyBfKos
+dnBSy20D8LIh1cCZOJ+cUOq8xN0JJky4IzWx+TSk9yeGfyFAlXdA9WRAVj6773an
+2GsRRNi4UeoMI+edwzi0cImISRBrsDcA/yxSBdxR1/0CgcAry0zR8Dp/1sWbgg8n
+K+yw5uZNS2/IDk4YTcDjehMnv9/ZqL2rydm1Ii5lc3625HTSCweQYju+uSnWJFY6
+lbPDdzhx1vjeZ/0KLdDEN9mj8mKLAUCUmxZUgTrHo0zoJOqCLi1E/c3VaeJQBYFr
+ncUj3rKPCSeGWAh/4wPu3z/gooU6FONOCSNVPMHUxQXkrDAqQxMAIl3GMbR5aIk/
+cPNfrU+1sDI3HI6aG2DNhkKtvtRYpOJfsn0m855TJryoCRkCgcAHnLZQEkXP624q
+Pq5i5OaKUUeVfIlxHW4S9ucTDw/+G3iHdV9Gxeq3bmMh5B8c8VL9YIHHTKn1xs+h
+iOolSuroDbzzjn+7wF6g2+6wxGg5G0JAiU2WNR4Lv1yJ57tkL42wmEhbzEdqtg47
+RPHPnKhBTxQ4dRMQ9/wCxFsgM1CuD4Fpog4VK06HGt9fXB2iDNQrZmgHbKuGmCL/
+p/9Ftzzg5fo/D3Vd28r2rVo1r4M/LmPuQ5ODWffn4leVNkkV3Gg=
 -----END RSA PRIVATE KEY-----
diff --git a/credentials/sealer.jks b/credentials/sealer.jks
index 47de93f..f10f00a 100644
Binary files a/credentials/sealer.jks and b/credentials/sealer.jks differ
diff --git a/credentials/sealer.kver b/credentials/sealer.kver
index d03abf1..aa1fae9 100644
--- a/credentials/sealer.kver
+++ b/credentials/sealer.kver
@@ -1,2 +1,2 @@
-#Wed Oct 02 14:46:56 UTC 2019
+#Wed Mar 24 15:54:24 UTC 2021
 CurrentVersion=1
diff --git a/credentials/secrets.properties b/credentials/secrets.properties
new file mode 100644
index 0000000..26d4af7
--- /dev/null
+++ b/credentials/secrets.properties
@@ -0,0 +1,13 @@
+# This is a reserved spot for most properties containing passwords or other secrets.
+# Created by install at 2021-03-24T15:54:24.596740Z
+
+# Access to internal AES encryption key
+idp.sealer.storePassword = changeit
+idp.sealer.keyPassword = changeit
+
+# Default access to LDAP authn and attribute stores. 
+idp.authn.LDAP.bindDNCredential              = myServicePassword
+idp.attribute.resolver.LDAP.bindDNCredential = %{idp.authn.LDAP.bindDNCredential:undefined}
+
+# Salt used to generate persistent/pairwise IDs, must be kept secret
+#idp.persistentId.salt = changethistosomethingrandom
diff --git a/edit-webapp/css/logout.css b/edit-webapp/css/logout.css
index 26f1893..dcd10d2 100644
--- a/edit-webapp/css/logout.css
+++ b/edit-webapp/css/logout.css
@@ -1,12 +1,17 @@
 /* Success/Failure indicators for logout propagation. */
-
-.success {
-    background: url(../images/success-32x32.png) no-repeat left center;
+li.logout {
     line-height: 36px;
     padding-left: 36px;
 }
-.failure {
+li.logout.success {
+    background: url(../images/success-32x32.png) no-repeat left center;
+}
+li.logout.failure {
+    background: url(../images/failure-32x32.png) no-repeat left center;
+}
+li.logout.pending{
+
+}
+li.logout.na {
     background: url(../images/failure-32x32.png) no-repeat left center;
-    line-height: 36px;
-    padding-left: 36px;
 }
diff --git a/flows/authn/conditions/account-locked/account-locked-flow.xml b/flows/authn/conditions/account-locked/account-locked-flow.xml
new file mode 100644
index 0000000..5fe7523
--- /dev/null
+++ b/flows/authn/conditions/account-locked/account-locked-flow.xml
@@ -0,0 +1,16 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd">
+
+    <!-- This is a placeholder flow that does nothing out of the box but reserves a subflow ID. -->
+
+    <!-- Rudimentary impediment to direct execution of subflow. -->
+    <input name="calledAsSubflow" type="boolean" required="true" />
+
+    <on-start>
+        <evaluate expression="'proceed'" />
+    </on-start>    
+
+    <end-state id="proceed" />
+
+</flow>
diff --git a/flows/authn/conditions/conditions-flow.xml b/flows/authn/conditions/conditions-flow.xml
new file mode 100644
index 0000000..53c4994
--- /dev/null
+++ b/flows/authn/conditions/conditions-flow.xml
@@ -0,0 +1,35 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+      abstract="true">
+
+    <!-- Rudimentary impediment to direct execution of subflow. -->
+    <input name="calledAsSubflow" type="boolean" required="true" />
+
+    <action-state id="ValidateUsernamePassword">
+        
+        <!-- Call outs for exceptional conditions. -->
+        <transition on="AccountWarning" to="CallExpiringPassword" />
+        <transition on="ExpiringPassword" to="CallExpiringPassword" />
+        <transition on="ExpiredPassword" to="CallExpiredPassword" />
+        <transition on="AccountLocked" to="CallAccountLocked" />
+        
+        <transition to="DisplayUsernamePasswordPage" />
+    </action-state>
+
+    <subflow-state id="CallExpiringPassword" subflow="authn/conditions/expiring-password">
+        <input name="calledAsSubflow" value="true" />
+        <transition on="proceed" to="ContinueSuccessfulAuthentication" />
+    </subflow-state>
+
+    <subflow-state id="CallExpiredPassword" subflow="authn/conditions/expired-password">
+        <input name="calledAsSubflow" value="true" />
+        <transition on="proceed" to="DisplayUsernamePasswordPage" />
+    </subflow-state>
+
+    <subflow-state id="CallAccountLocked" subflow="authn/conditions/account-locked">
+        <input name="calledAsSubflow" value="true" />
+        <transition on="proceed" to="DisplayUsernamePasswordPage" />
+    </subflow-state>
+
+</flow>
diff --git a/flows/authn/conditions/expired-password/expired-password-flow.xml b/flows/authn/conditions/expired-password/expired-password-flow.xml
new file mode 100644
index 0000000..5fe7523
--- /dev/null
+++ b/flows/authn/conditions/expired-password/expired-password-flow.xml
@@ -0,0 +1,16 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd">
+
+    <!-- This is a placeholder flow that does nothing out of the box but reserves a subflow ID. -->
+
+    <!-- Rudimentary impediment to direct execution of subflow. -->
+    <input name="calledAsSubflow" type="boolean" required="true" />
+
+    <on-start>
+        <evaluate expression="'proceed'" />
+    </on-start>    
+
+    <end-state id="proceed" />
+
+</flow>
diff --git a/flows/authn/conditions/expiring-password/expiring-password-flow.xml b/flows/authn/conditions/expiring-password/expiring-password-flow.xml
new file mode 100644
index 0000000..10e041e
--- /dev/null
+++ b/flows/authn/conditions/expiring-password/expiring-password-flow.xml
@@ -0,0 +1,33 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd">
+
+    <!--
+    This is an example flow that displays a view template in response to an expiring password.
+    The view might display a pointer to the password change portal while automatically continuing
+    after a few seconds.
+    -->
+
+    <!-- Rudimentary impediment to direct execution of subflow. -->
+    <input name="calledAsSubflow" type="boolean" required="true" />
+
+    <view-state id="ExpiringPassword" view="intercept/expiring-password">
+    	<attribute name="csrf_excluded" value="true" type="boolean"/>
+        <on-render>
+            <evaluate expression="environment" result="viewScope.environment" />
+            <evaluate expression="opensamlProfileRequestContext" result="viewScope.profileRequestContext" />
+            <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext))" result="viewScope.authenticationContext" />
+            <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationErrorContext))" result="viewScope.authenticationErrorContext" />
+            <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationWarningContext))" result="viewScope.authenticationWarningContext" />
+            <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.LDAPResponseContext))" result="viewScope.ldapResponseContext" />
+            <evaluate expression="T(net.shibboleth.utilities.java.support.codec.HTMLEncoder)" result="viewScope.encoder" />
+            <evaluate expression="flowRequestContext.getExternalContext().getNativeRequest()" result="viewScope.request" />
+            <evaluate expression="flowRequestContext.getExternalContext().getNativeResponse()" result="viewScope.response" />
+            <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.CustomViewContext') ? flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.CustomViewContext') : null" result="viewScope.custom" />
+        </on-render>
+        <transition on="proceed" to="proceed" />
+    </view-state>
+
+    <end-state id="proceed" />
+
+</flow>
diff --git a/flows/user/prefs/prefs-flow.xml b/flows/user/prefs/prefs-flow.xml
new file mode 100644
index 0000000..c79093b
--- /dev/null
+++ b/flows/user/prefs/prefs-flow.xml
@@ -0,0 +1,25 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd">
+
+    <!--
+    This flow allows a user to adjust various client-side preferences.
+    
+    It's partly example, partly a placeholder to allow adjustment of a few
+    existing cookie-based options used by some features of the IdP for the time
+    being while leaving the option of a more comprehensive UI down the road.
+    
+    As a flow, it's nothing much, just a view rendered to push some JS into
+    the browser to maintain things. Notably, it doesn't require a user login.
+    -->
+
+    <end-state id="RenderView" view="user-prefs">
+        <on-entry>
+            <evaluate expression="environment" result="requestScope.environment" />
+            <evaluate expression="T(net.shibboleth.utilities.java.support.codec.HTMLEncoder)" result="requestScope.encoder" />
+            <evaluate expression="flowRequestContext.getExternalContext().getNativeRequest()" result="requestScope.request" />
+            <evaluate expression="flowRequestContext.getExternalContext().getNativeResponse()" result="requestScope.response" />
+            <evaluate expression="flowRequestContext.getActiveFlow().getApplicationContext().containsBean('shibboleth.CustomViewContext') ? flowRequestContext.getActiveFlow().getApplicationContext().getBean('shibboleth.CustomViewContext') : null" result="requestScope.custom" />
+        </on-entry>
+    </end-state>
+</flow>
diff --git a/metadata/idp-metadata.xml b/metadata/idp-metadata.xml
deleted file mode 100644
index a1f33a1..0000000
--- a/metadata/idp-metadata.xml
+++ /dev/null
@@ -1,251 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-     This is example metadata only. Do *NOT* supply it as is without review,
-     and do *NOT* provide it in real time to your partners.
-
-     This metadata is not dynamic - it will not change as your configuration changes.
--->
-<EntityDescriptor  xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:req-attr="urn:oasis:names:tc:SAML:protocol:ext:req-attr" validUntil="2019-10-02T14:46:57.225Z" entityID="https://idp.example.org/idp/shibboleth">
-
-    <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0">
-
-        <Extensions>
-            <shibmd:Scope regexp="false">example.org</shibmd:Scope>
-<!--
-    Fill in the details for your IdP here 
-
-            <mdui:UIInfo>
-                <mdui:DisplayName xml:lang="en">A Name for the IdP at idp.example.org</mdui:DisplayName>
-                <mdui:Description xml:lang="en">Enter a description of your IdP at idp.example.org</mdui:Description>
-                <mdui:Logo height="80" width="80">https://idp.example.org/Path/To/Logo.png</mdui:Logo>
-            </mdui:UIInfo>
--->
-        </Extensions>
-
-        <!-- First signing certificate is BackChannel, the Second is FrontChannel -->
-        <KeyDescriptor use="signing">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEKDCCApCgAwIBAgIVAJ0iknQBSFLEkl3ybj6HYSWkOw+CMA0GCSqGSIb3DQEB
-CwUAMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzAeFw0xOTEwMDIxNDQ2NTZa
-Fw0zOTEwMDIxNDQ2NTZaMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzCCAaIw
-DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJJI3OlyhXVII2YS2VGAZlCy/PE1
-RPLwTb9hIrBETcpA3JwVba2hBq8v0lWGpWkmvQfsjH+bKRJe611EyXwWQH04qGCU
-RDCFKBU8E9P87m6GTeh+DC6eVXxOB2h0pf3Zmktf48hlhV1X24NwIjba6v9X8oHF
-FTFFqopOPAaJWnODPQyul/d4DqkqkBfQer6p0RiDL/V79WpTVG87pJxmGH2FbchP
-PivVO9sMYfC5lqe37x/zu8huU0jDnB20eqEjnVNjvPjzbF36xPA06770FJuPxCYd
-5oebut50pO7DZY7MZGu4/UME0JfDrnCsyPz2L1gdxXX28mydAVL3YwIajZzuPVwJ
-HC+HJuF3YNgIZ7ZO6uN2Cyi1tKKAE5n3G19L8NLLW44MVxkS9ox9cFvw5e2Zm+ek
-Hh6iu6Y9/blyuFjlqVaffM6l6NVnAAXPiIpwnBdzWdJqMcJzgC5bTqOGEZdeR9hT
-ei0e1s+bmBj3/3cOB3hII74P5sCuGLfiYqSQzQIDAQABo2UwYzAdBgNVHQ4EFgQU
-hb0zxPkLe5m7vmD8AH0fjATSaIwwQgYDVR0RBDswOYIPaWRwLmV4YW1wbGUub3Jn
-hiZodHRwczovL2lkcC5leGFtcGxlLm9yZy9pZHAvc2hpYmJvbGV0aDANBgkqhkiG
-9w0BAQsFAAOCAYEADQ17KGVQJ6AZTqDUDxVAfrTlFXysuvQg1WntrMB1PUzlb6Pa
-AO6Nb24YiY0PonSk7iz+gOg4P/V2b9wX4NXPBcX5h86fxR8R3cwZYsYKhwBBQ6uo
-UZnqtNyYNY/3hM2Dj8sR1PMijwgNmo7KOzzBPKKhID2dtGL3bS3TrX8xjmc7NK+r
-5VE9LrK3kG3ht3qM0I7iPMNuQXBOuduRG8WGD8NsFwHcYfORJmK5Ac/AtjHMVLF0
-x+m4LyLxP53t9/5+5fiJ3bghXM7Uuzjjmes6fdZyUcxinrwFxvSIGz3gqXf35Omf
-EwFemewB5B9GkAVXJSq2J64+iWXTo556YEC/RUrX6ZA5db6zHIeHX4BSf7U5YUBm
-LRJ/RJZKKPKEBBJgvh8vUFLF64tDn0c9x3n1mw+ZLHnPcjdX5v/stLVgR020vRx7
-8CGsrydmj+80Gm3Ji1eGJfD2LdUslve3bNerEW2AUM3DFx6wDlR5K/0ix98Ah1w0
-AuAeyajXyLR9NkPm
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-        <KeyDescriptor use="signing">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEJzCCAo+gAwIBAgIUOCYqGG6JElEG1wHKL7CvULRTvEswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NVoX
-DTM5MTAwMjE0NDY1NVowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwkiDw0dpZmup6VpfVXkib8fiv7KF
-T1Z3z6tq7c/ki/CH2x8BYtLPNgIvQa8KhggHUKG+rRU9yBwWg4Yvdsi05h5pJwcE
-xE1hwE7oVWiY+DtMggv4zVbDm0TnbvJvXN9eYXNn/e9RL3hD3umPIzDSli3wwiNg
-GvMesn/4Npq6ERi80CPIkUENkL3N7XTDX+Fy/mhXCxc73Dv3Meo0qk0pii005nV1
-vHCP9jsUgPfDCBScUuikfQ8V9SPLgOSf1x3vc5RqSPWaHgLesqoXpFFTthlVjB8j
-cUzqjQllhOS6LKWJE7VIfV6MdpfkRZBWhsaeuT7I48kRmFuALLnIopkclqu3HtON
-0Fgd1oPPBHa04bLcPqbneqGL+2RzZOdnuarTtY+JOuCRnE1qCWUeRoH2yeMMdKPy
-amX6HZJ35Vsk3uJxJX/IyipduZ+nHPC5qi52Elu+oyBrJwTbVAhhlXwPehC6nU/c
-1LUnbo3M4SGOYWuPmI1ko5KF91MVUU7ttmkFAgMBAAGjZTBjMB0GA1UdDgQWBBQ1
-CuX1jKcG8rdC0xBBveSJAYoFfzBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
-Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQA89rYZmayIfst0cGyt+zdeHpnvyo+zVfAk7OztXF5OXsakX9TV
-Iq8ur1lq4Q4KC/Ev+9p1za1gP7Ea9ugFJinuVa6ntpzGP0vh42pmphLNaRFvnPch
-pwgGCvcF2leYG6zZl/Qln0Kbv+pyByens7xPdKKA8U5ySVkouLuw7017XSIulPtW
-u5tPz51awJubHCK+FckcVH0yZZg44s4HmjzLpJCdslMIxmhtX7DW3vtqH1pL9Mir
-3qykySFUJGthV3ndHesG08y3Tni5HZaRqHHafGRBiezO8JCwVvWrdC29SdAwY2i0
-HhKB7zCDOpYrh3o8TTx3ZJd+6Uel/e0bCefs9uhMj7O5ErNySHyTtNRrFxTl2c98
-RDweMp6NLfm+P3+EqJycmpR9CKudcL6RUikN9hDvy6qqG2t5fW7pvU/+mzRm/3Cf
-gMxKHQM+OAry1E6pQSYh8qkPZYDezwiz4gINxn7SFAxFJQcTlaSVmFHLOQV7TetI
-g4sTktRrBmgU/vk=
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-        <KeyDescriptor use="encryption">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEJzCCAo+gAwIBAgIUe0fsxBFnYrItqaF1zUSc7oTFFhswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NloX
-DTM5MTAwMjE0NDY1NlowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAlBwK5LM+22M0RLLhaVoTlgGJlF75
-0hfDGl45GqSVh7gB4X93icnoh2mUoGq/wgqx+YwCJ04hEJF0BXGRzmP5qQdSPw/z
-VV2e90emvoFvRD0OWrRDo4kn9GO2a4t8nAdLNe8dclsEpxyKktvmppMbna0jNGau
-h8OMsSNlTKH8C6qzIUtxOGnN75Qw1JAQ0N6U0Jl9w7x1LoR2tiyiTDKMAyx8v7xu
-eurxduh/Y1g/2fxi3UGA0i0znwTjEM0eZ/3JQMtuCKW6mTNTF/klBWiEhP6Vm3Yk
-WgbYDMgahiaEo2dzxmKgFfFysoSxkfV93zSh31+zKovj5NpNEU9LrlFDD8iRYPlK
-ZKjdleWOsGFbtyfvSV8Xq1bJvn9LScH02gCDbjkYFOlGgs32nGIqe4tr7ekT8A60
-S9dtIV54834ZdntBRzPkaLRaHb6FWY74U5+o1U1spd2JhWvFMlrkHCghcIWKmG87
-pzmZBFcyxSBIK0E6dhjm3EGXMmWdn80Sr1lxAgMBAAGjZTBjMB0GA1UdDgQWBBQ8
-+tUYkLiwLXUxRdIcfwUUs3s+dTBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
-Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQBXnSl1RPlziZEpGUc3FGoQCpsu6FovK7jlieATyKWD3NY7lha6
-iOqiyxpNnrekh3Sf3XvmwvoxBHULQNS06GMMej8WtFBSaomNIkuztzMUAEmil2UF
-rP1xT0Gx+lT/Don9e60dGMMl2FWYIHobkQj4yhjSW6yN/emQRkwOhkj1DRGkZ1Zz
-wIRtH7/VT1YXH6n4P6lWNMgV+GInhT7ogitN5Vf6tCfMaZtowu3bb2I1gDlgYY/v
-0TrokTQteO7vcf+EpTODPRBiFV/Wwub5r8BDN4O3qGt52f2lhlEqdupFArooNVyF
-tU+zmj0gaclvvBBAaN2oh0Tj+j7HBh1YWB8p93vm62dKqY/9L9xSNAni6EI5o7dm
-58OUngvQopb7U7MDDuH2gM0XiH/R2BNp4c7/jqBP2Of5Bg68yKCZHB7D5XOJbQLf
-gjm4h9tRHtDijVkHcuIEICBwrie+JSEL225UnTfsesPiArDvo5BhQeNc3q1CPJgF
-2QOuaDoiGwFbc5s=
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-
-        <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://idp.example.org:8443/idp/profile/SAML1/SOAP/ArtifactResolution" index="1"/>
-        <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/ArtifactResolution" index="2"/>
-
-        <!--
-        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.org/idp/profile/SAML2/Redirect/SLO"/>
-        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.example.org/idp/profile/SAML2/POST/SLO"/>
-        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://idp.example.org/idp/profile/SAML2/POST-SimpleSign/SLO"/>
-        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/SLO"/>
-        -->
-
-        <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest" Location="https://idp.example.org/idp/profile/Shibboleth/SSO"/>
-        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" req-attr:supportsRequestedAttributes="true" Location="https://idp.example.org/idp/profile/SAML2/POST/SSO"/>
-        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" req-attr:supportsRequestedAttributes="true" Location="https://idp.example.org/idp/profile/SAML2/POST-SimpleSign/SSO"/>
-        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" req-attr:supportsRequestedAttributes="true" Location="https://idp.example.org/idp/profile/SAML2/Redirect/SSO"/>
-
-    </IDPSSODescriptor>
-
-
-    <AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol">
-
-        <Extensions>
-            <shibmd:Scope regexp="false">example.org</shibmd:Scope>
-        </Extensions>
-
-        <!-- First signing certificate is BackChannel, the Second is FrontChannel -->
-        <KeyDescriptor use="signing">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEKDCCApCgAwIBAgIVAJ0iknQBSFLEkl3ybj6HYSWkOw+CMA0GCSqGSIb3DQEB
-CwUAMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzAeFw0xOTEwMDIxNDQ2NTZa
-Fw0zOTEwMDIxNDQ2NTZaMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLm9yZzCCAaIw
-DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJJI3OlyhXVII2YS2VGAZlCy/PE1
-RPLwTb9hIrBETcpA3JwVba2hBq8v0lWGpWkmvQfsjH+bKRJe611EyXwWQH04qGCU
-RDCFKBU8E9P87m6GTeh+DC6eVXxOB2h0pf3Zmktf48hlhV1X24NwIjba6v9X8oHF
-FTFFqopOPAaJWnODPQyul/d4DqkqkBfQer6p0RiDL/V79WpTVG87pJxmGH2FbchP
-PivVO9sMYfC5lqe37x/zu8huU0jDnB20eqEjnVNjvPjzbF36xPA06770FJuPxCYd
-5oebut50pO7DZY7MZGu4/UME0JfDrnCsyPz2L1gdxXX28mydAVL3YwIajZzuPVwJ
-HC+HJuF3YNgIZ7ZO6uN2Cyi1tKKAE5n3G19L8NLLW44MVxkS9ox9cFvw5e2Zm+ek
-Hh6iu6Y9/blyuFjlqVaffM6l6NVnAAXPiIpwnBdzWdJqMcJzgC5bTqOGEZdeR9hT
-ei0e1s+bmBj3/3cOB3hII74P5sCuGLfiYqSQzQIDAQABo2UwYzAdBgNVHQ4EFgQU
-hb0zxPkLe5m7vmD8AH0fjATSaIwwQgYDVR0RBDswOYIPaWRwLmV4YW1wbGUub3Jn
-hiZodHRwczovL2lkcC5leGFtcGxlLm9yZy9pZHAvc2hpYmJvbGV0aDANBgkqhkiG
-9w0BAQsFAAOCAYEADQ17KGVQJ6AZTqDUDxVAfrTlFXysuvQg1WntrMB1PUzlb6Pa
-AO6Nb24YiY0PonSk7iz+gOg4P/V2b9wX4NXPBcX5h86fxR8R3cwZYsYKhwBBQ6uo
-UZnqtNyYNY/3hM2Dj8sR1PMijwgNmo7KOzzBPKKhID2dtGL3bS3TrX8xjmc7NK+r
-5VE9LrK3kG3ht3qM0I7iPMNuQXBOuduRG8WGD8NsFwHcYfORJmK5Ac/AtjHMVLF0
-x+m4LyLxP53t9/5+5fiJ3bghXM7Uuzjjmes6fdZyUcxinrwFxvSIGz3gqXf35Omf
-EwFemewB5B9GkAVXJSq2J64+iWXTo556YEC/RUrX6ZA5db6zHIeHX4BSf7U5YUBm
-LRJ/RJZKKPKEBBJgvh8vUFLF64tDn0c9x3n1mw+ZLHnPcjdX5v/stLVgR020vRx7
-8CGsrydmj+80Gm3Ji1eGJfD2LdUslve3bNerEW2AUM3DFx6wDlR5K/0ix98Ah1w0
-AuAeyajXyLR9NkPm
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-        <KeyDescriptor use="signing">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEJzCCAo+gAwIBAgIUOCYqGG6JElEG1wHKL7CvULRTvEswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NVoX
-DTM5MTAwMjE0NDY1NVowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwkiDw0dpZmup6VpfVXkib8fiv7KF
-T1Z3z6tq7c/ki/CH2x8BYtLPNgIvQa8KhggHUKG+rRU9yBwWg4Yvdsi05h5pJwcE
-xE1hwE7oVWiY+DtMggv4zVbDm0TnbvJvXN9eYXNn/e9RL3hD3umPIzDSli3wwiNg
-GvMesn/4Npq6ERi80CPIkUENkL3N7XTDX+Fy/mhXCxc73Dv3Meo0qk0pii005nV1
-vHCP9jsUgPfDCBScUuikfQ8V9SPLgOSf1x3vc5RqSPWaHgLesqoXpFFTthlVjB8j
-cUzqjQllhOS6LKWJE7VIfV6MdpfkRZBWhsaeuT7I48kRmFuALLnIopkclqu3HtON
-0Fgd1oPPBHa04bLcPqbneqGL+2RzZOdnuarTtY+JOuCRnE1qCWUeRoH2yeMMdKPy
-amX6HZJ35Vsk3uJxJX/IyipduZ+nHPC5qi52Elu+oyBrJwTbVAhhlXwPehC6nU/c
-1LUnbo3M4SGOYWuPmI1ko5KF91MVUU7ttmkFAgMBAAGjZTBjMB0GA1UdDgQWBBQ1
-CuX1jKcG8rdC0xBBveSJAYoFfzBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
-Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQA89rYZmayIfst0cGyt+zdeHpnvyo+zVfAk7OztXF5OXsakX9TV
-Iq8ur1lq4Q4KC/Ev+9p1za1gP7Ea9ugFJinuVa6ntpzGP0vh42pmphLNaRFvnPch
-pwgGCvcF2leYG6zZl/Qln0Kbv+pyByens7xPdKKA8U5ySVkouLuw7017XSIulPtW
-u5tPz51awJubHCK+FckcVH0yZZg44s4HmjzLpJCdslMIxmhtX7DW3vtqH1pL9Mir
-3qykySFUJGthV3ndHesG08y3Tni5HZaRqHHafGRBiezO8JCwVvWrdC29SdAwY2i0
-HhKB7zCDOpYrh3o8TTx3ZJd+6Uel/e0bCefs9uhMj7O5ErNySHyTtNRrFxTl2c98
-RDweMp6NLfm+P3+EqJycmpR9CKudcL6RUikN9hDvy6qqG2t5fW7pvU/+mzRm/3Cf
-gMxKHQM+OAry1E6pQSYh8qkPZYDezwiz4gINxn7SFAxFJQcTlaSVmFHLOQV7TetI
-g4sTktRrBmgU/vk=
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-        <KeyDescriptor use="encryption">
-            <ds:KeyInfo>
-                    <ds:X509Data>
-                        <ds:X509Certificate>
-MIIEJzCCAo+gAwIBAgIUe0fsxBFnYrItqaF1zUSc7oTFFhswDQYJKoZIhvcNAQEL
-BQAwGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMB4XDTE5MTAwMjE0NDY1NloX
-DTM5MTAwMjE0NDY1NlowGjEYMBYGA1UEAwwPaWRwLmV4YW1wbGUub3JnMIIBojAN
-BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAlBwK5LM+22M0RLLhaVoTlgGJlF75
-0hfDGl45GqSVh7gB4X93icnoh2mUoGq/wgqx+YwCJ04hEJF0BXGRzmP5qQdSPw/z
-VV2e90emvoFvRD0OWrRDo4kn9GO2a4t8nAdLNe8dclsEpxyKktvmppMbna0jNGau
-h8OMsSNlTKH8C6qzIUtxOGnN75Qw1JAQ0N6U0Jl9w7x1LoR2tiyiTDKMAyx8v7xu
-eurxduh/Y1g/2fxi3UGA0i0znwTjEM0eZ/3JQMtuCKW6mTNTF/klBWiEhP6Vm3Yk
-WgbYDMgahiaEo2dzxmKgFfFysoSxkfV93zSh31+zKovj5NpNEU9LrlFDD8iRYPlK
-ZKjdleWOsGFbtyfvSV8Xq1bJvn9LScH02gCDbjkYFOlGgs32nGIqe4tr7ekT8A60
-S9dtIV54834ZdntBRzPkaLRaHb6FWY74U5+o1U1spd2JhWvFMlrkHCghcIWKmG87
-pzmZBFcyxSBIK0E6dhjm3EGXMmWdn80Sr1lxAgMBAAGjZTBjMB0GA1UdDgQWBBQ8
-+tUYkLiwLXUxRdIcfwUUs3s+dTBCBgNVHREEOzA5gg9pZHAuZXhhbXBsZS5vcmeG
-Jmh0dHBzOi8vaWRwLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3
-DQEBCwUAA4IBgQBXnSl1RPlziZEpGUc3FGoQCpsu6FovK7jlieATyKWD3NY7lha6
-iOqiyxpNnrekh3Sf3XvmwvoxBHULQNS06GMMej8WtFBSaomNIkuztzMUAEmil2UF
-rP1xT0Gx+lT/Don9e60dGMMl2FWYIHobkQj4yhjSW6yN/emQRkwOhkj1DRGkZ1Zz
-wIRtH7/VT1YXH6n4P6lWNMgV+GInhT7ogitN5Vf6tCfMaZtowu3bb2I1gDlgYY/v
-0TrokTQteO7vcf+EpTODPRBiFV/Wwub5r8BDN4O3qGt52f2lhlEqdupFArooNVyF
-tU+zmj0gaclvvBBAaN2oh0Tj+j7HBh1YWB8p93vm62dKqY/9L9xSNAni6EI5o7dm
-58OUngvQopb7U7MDDuH2gM0XiH/R2BNp4c7/jqBP2Of5Bg68yKCZHB7D5XOJbQLf
-gjm4h9tRHtDijVkHcuIEICBwrie+JSEL225UnTfsesPiArDvo5BhQeNc3q1CPJgF
-2QOuaDoiGwFbc5s=
-                        </ds:X509Certificate>
-                    </ds:X509Data>
-            </ds:KeyInfo>
-
-        </KeyDescriptor>
-
-        <AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://idp.example.org:8443/idp/profile/SAML1/SOAP/AttributeQuery"/>
-        <!-- <AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/AttributeQuery"/> -->
-        <!-- If you uncomment the above you should add urn:oasis:names:tc:SAML:2.0:protocol to the protocolSupportEnumeration above -->
-
-    </AttributeAuthorityDescriptor>
-
-</EntityDescriptor>
diff --git a/views/admin/hello.vm b/views/admin/hello.vm
new file mode 100644
index 0000000..33a0528
--- /dev/null
+++ b/views/admin/hello.vm
@@ -0,0 +1,73 @@
+##
+## Velocity Template for Hello World page.
+##
+## Velocity context will contain the following properties
+## flowRequestContext - the Spring Web Flow RequestContext
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## profileRequestContext - root of context tree
+## subjectContext - ProfileRequestContext -> SubjectContext
+## attributeContext - ProfileRequestContext -> AttributeContext
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <title>#springMessageText("idp.title", "Web Login Service") - #springMessageText("hello-world.title", "Hello World")</title>
+    <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
+  </head>
+  
+  <body>
+    <div class="wrapper">
+      <div class="container" style="width: 100%">
+        <header>
+          <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
+          <h3>#springMessageText("idp.title", "Web Login Service")</h3>
+        </header>
+                
+        <div class="content">
+          <h4>#springMessageText("hello-world.greeting", "Greetings"), <em>$encoder.encodeForHTML($subjectContext.getPrincipalName())</em></h4>
+          <br/>
+          <h4>Authenticated By</h4>
+          #foreach ($result in $subjectContext.getAuthenticationResults().entrySet())
+            <blockquote>$encoder.encodeForHTML($result.getKey())</blockquote>
+          #end
+          <br/>
+          <h4>Java Principals in Subjects</h4>
+          #foreach ($s in $subjectContext.getSubjects())
+            #foreach ($p in $s.getPrincipals())
+              <blockquote>$encoder.encodeForHTML($p)<blockquote>
+            #end
+          #end
+          #if ($attributeContext && !$attributeContext.getUnfilteredIdPAttributes().isEmpty())
+            <br/>
+            <h4>Attributes:</h4>
+            #foreach ($a in $attributeContext.getUnfilteredIdPAttributes())
+              #if (!$a.getValues().isEmpty())
+                <br/>
+                <h5>$encoder.encodeForHTML($a.getId())</h5>
+                  #foreach ($v in $a.getValues())
+                    <blockquote>$encoder.encodeForHTML($v.getDisplayValue())</blockquote>
+                  #end
+              #end
+            #end
+          #end
+        </div>
+
+        <header>
+          <h3><a href="$request.getContextPath()/profile/admin/hello">#springMessageText("hello-world.reload", "Reload the Page")</a></h3>
+        </header>
+      </div>
+
+      <footer>
+        <div class="container container-footer">
+          <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
+        </div>
+      </footer>
+    </div>
+  </body>
+</html>
diff --git a/views/admin/unlock-keys.vm b/views/admin/unlock-keys.vm
deleted file mode 100644
index 3b15f3e..0000000
--- a/views/admin/unlock-keys.vm
+++ /dev/null
@@ -1,96 +0,0 @@
-##
-## Velocity Template for Attended Startup Unlock Utility
-##
-## Velocity context will contain the following properties:
-## flowRequestContext - the Spring Web Flow RequestContext
-## request - HttpServletRequest
-## response - HttpServletResponse
-## profileRequestContext
-## environment - Spring Environment object for property resolution
-## custom - arbitrary object injected by deployer
-##
-#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
-#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.unlock-keys.title", "Attended Restart Key Unlock"))
-#set ($eventId = $profileRequestContext.getSubcontext("org.opensaml.profile.context.EventContext").getEvent())
-#set ($state = $flowRequestContext.getCurrentState().getId())
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        <title>$title - $titleSuffix</title>
-        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
-    </head>
-    
-    <body>
-    <div class="wrapper">
-        <div class="container">
-            <header>
-                <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
-                <h3>$title - $titleSuffix</h3>
-            </header>
-        
-            <div class="content">
-            #if ($state == "end")
-                <strong>#springMessageText("idp.unlock-keys.complete", "The system is unlocked and ready for use.")</strong>
-                <p><a href="$request.getContextPath()/profile/SAML2/Unsolicited/SSO?providerId=https://sp.example.org/shibboleth">Validation Link</a></p>
-            #else
-                #if ($eventId == "InvalidMessage")
-                    <p class="form-element form-error">
-                    #springMessageText("idp.unlock-keys.error", "Unlock failed; check log for specific message.")
-                    </p>
-                    <br/><br/>
-                #end
-            
-                <form action="$flowExecutionUrl" method="post">
-                
-                  <!--
-                  If you have multiple key strategies defined, you'll need multiple pairs of form fields for
-                  the passwords, labeled in the order they're fed into the shibboleth.unlock-keys.KeyStrategies
-                  bean. If you have none, remove the fields.
-                  -->
-
-                  <div class="form-element-wrapper">
-                    <label for="password">#springMessageText("idp.unlock-keys.keystorePassword", "DataSealer Keystore Password")</label>
-                    <input class="form-element form-field" id="password" name="keystorePassword" type="password">
-                  </div>
-
-                  <div class="form-element-wrapper">
-                    <label for="password">#springMessageText("idp.unlock-keys.keyPassword", "DataSealer Key Password")</label>
-                    <input class="form-element form-field" id="password" name="keyPassword" type="password">
-                  </div>
-
-                  <!--
-                  If you have multiple private keys defined, you'll need a form field for each passwords, labeled in the order
-                  they're fed into the shibboleth.unlock-keys.Credentials/PrivateKeys beans. If you have none, remove the fields.
-                  -->
-
-                  <div class="form-element-wrapper">
-                    <label for="password">#springMessageText("idp.unlock-keys.privateKeyPassword", "Private Key Password")</label>
-                    <input class="form-element form-field" id="password" name="privateKeyPassword" type="password">
-                  </div>
-                  
-                  <div class="form-element-wrapper">
-                    <button class="form-element form-button" type="submit" name="_eventId_proceed"
-                        >#springMessageText("idp.unlock-keys.unlock", "Unlock")</button>
-                  </div>
-
-                  <div class="form-element-wrapper">
-                    <button class="form-element form-button" type="submit" name="_eventId_cancel"
-                        >#springMessageText("idp.unlock-keys.cancel", "Cancel")</button>
-                  </div>
-                  
-                </form>
-            #end
-            </div>
-        </div>
-
-        <footer>
-            <div class="container container-footer">
-                <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-            </div>
-        </footer>
-        
-    </div>
-    </body>
-</html>
\ No newline at end of file
diff --git a/views/duo.vm b/views/duo.vm
deleted file mode 100644
index cf4f96a..0000000
--- a/views/duo.vm
+++ /dev/null
@@ -1,83 +0,0 @@
-##
-## Velocity Template for Duo login view-state
-##
-## Velocity context will contain the following properties
-## flowExecutionUrl - the form action location
-## flowRequestContext - the Spring Web Flow RequestContext
-## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
-## profileRequestContext - root of context tree
-## authenticationContext - context with authentication request information
-## rpUIContext - the context with SP UI information from the metadata
-## canonicalUsername - name of user passed to Duo
-## duoHost - API hostname for Duo frame
-## duoRequest - signed Duo request message
-## duoScriptPath - path to Duo JavaScript source
-## encoder - HTMLEncoder class
-## request - HttpServletRequest
-## response - HttpServletResponse
-## environment - Spring Environment object for property resolution
-## custom - arbitrary object injected by deployer
-##
-<!DOCTYPE html>
-<html>
-<head>
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>#springMessageText("idp.title", "Web Login Service")</title>
-    <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
-    <style>
-      #duo_iframe {
-        width: 100%;
-        min-width: 304px;
-        max-width: 620px;
-        height: 330px;
-      }
-    </style>
-</head>
-<body>
-    <div class="wrapper">
-      <div class="container">
-        <header>
-          <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
-        </header>
-
-        <div class="content">
-          <div class="column one">
-          
-            <h3>#springMessageText("idp.login.duoRequired", "Authentication with Duo is required for the requested service.")</h3>
-
-            <noscript>#springMessageText("idp.login.duoNoScript", "The Duo service requires JavaScript.")</noscript>          
-            <script src="$request.getContextPath()$duoScriptPath"></script>
-            <iframe id="duo_iframe"
-                data-host="$duoHost"
-                data-sig-request="$duoRequest"
-                data-post-action="$flowExecutionUrl"
-                frameborder="0"
-            >
-            </iframe>
-            <form id="duo_form" method="post">
-                <input type="hidden" name="_eventId" value="proceed" />
-
-            </form>
-            
-            <h3 style="text-align: center">
-                <a href="$flowExecutionUrl&_eventId=cancel">#springMessageText("idp.login.duoCancel", "Cancel this Request")</a>
-            </h3>
-          </div>
-          <div class="column two">
-            <ul class="list list-help">
-              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
-            </ul>
-          </div>
-        </div>
-      </div>
-
-      <footer>
-        <div class="container container-footer">
-          <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-        </div>
-      </footer>
-    </div>
-</body>
-</html>
diff --git a/views/error.vm b/views/error.vm
index dcb8e2b..a44bd6f 100644
--- a/views/error.vm
+++ b/views/error.vm
@@ -34,10 +34,12 @@
     #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error"))
     #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix"))
     #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId"))
+    $response.setStatus(500)
 #else
 	## This is a catch-all that theoretically shouldn't happen?
     #set ($titleSuffix = $defaultTitleSuffix)
     #set ($message = $springMacroRequestContext.getMessage("idp.message", "An unidentified error occurred."))
+    $response.setStatus(500)
 #end
 ##
 <!DOCTYPE html>
diff --git a/views/intercept/attribute-release.vm b/views/intercept/attribute-release.vm
deleted file mode 100644
index 20bde46..0000000
--- a/views/intercept/attribute-release.vm
+++ /dev/null
@@ -1,159 +0,0 @@
-##
-## Velocity Template for DisplayAttributeReleasePage view-state
-##
-## Velocity context will contain the following properties :
-##
-## attributeReleaseContext - context holding consentable attributes
-## attributeReleaseFlowDescriptor - attribute consent flow descriptor
-## attributeDisplayNameFunction - function to display attribute name
-## attributeDisplayDescriptionFunction - function to display attribute description
-## consentContext - context representing the state of a consent flow
-## encoder - HTMLEncoder class
-## flowExecutionKey - SWF execution key (this is built into the flowExecutionUrl)
-## flowExecutionUrl - form action location
-## flowRequestContext - Spring Web Flow RequestContext
-## profileRequestContext - OpenSAML profile request context
-## request - HttpServletRequest
-## response - HttpServletResponse
-## rpUIContext - context with SP UI information from the metadata
-## environment - Spring Environment object for property resolution
-#set ($serviceName = $rpUIContext.serviceName)
-#set ($serviceDescription = $rpUIContext.serviceDescription)
-#set ($informationURL = $rpUIContext.informationURL)
-#set ($privacyStatementURL = $rpUIContext.privacyStatementURL)
-#set ($rpOrganizationLogo = $rpUIContext.getLogo())
-#set ($rpOrganizationName = $rpUIContext.organizationName)
-#set ($replaceDollarWithNewline = true)
-##
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="UTF-8">
-        <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/consent.css">
-        <title>#springMessageText("idp.attribute-release.title", "Information Release")</title>
-    </head>
-    <body>
-        <form action="$flowExecutionUrl" method="post" style="padding:10px" >
-            <div class="box">
-                <header>
-                    <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")" class="federation_logo">
-                    #if ($rpOrganizationLogo)
-                        <img src="$encoder.encodeForHTMLAttribute($rpOrganizationLogo)" alt="logo for $encoder.encodeForHTMLAttribute($serviceName)" class="organization_logo">
-                    #end
-                </header>
-                #if ($serviceName)
-                    <p style="margin-top: 70px;">
-                        #springMessageText("idp.attribute-release.serviceNameLabel", "You are about to access the service:")<br>
-                        <span class="service_name">$serviceName</span>
-                        #if ($rpOrganizationName)
-                            #springMessageText("idp.attribute-release.of", "of") <span class="organization_name">$encoder.encodeForHTML($rpOrganizationName)</span>
-                        #end
-                    </p>
-                #end
-                #if ($serviceDescription)
-                    <p style="margin-top: 10px;">
-                        #springMessageText("idp.attribute-release.serviceDescriptionLabel", "Description as provided by this service:")<br>
-                        <span class="service_description">$encoder.encodeForHTML($serviceDescription)</span>
-                        <br>
-                    </p>
-                #end
-                #if ($informationURL)
-                    <p style="margin-top: 10px;">
-                        <a href="$informationURL">#springMessageText("idp.attribute-release.informationURLLabel", "Additional information about the service")</a>
-                    </p>
-                #end
-                <div id="attributeRelease">
-                    <table>
-                        <thead>
-                            <tr>
-                                <th colspan="3">
-                                    #springMessageText("idp.attribute-release.attributesHeader", "Information to be Provided to Service")
-                                </th>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            #foreach ($attribute in $attributeReleaseContext.getConsentableAttributes().values())
-                                <tr>
-                                    <td>$encoder.encodeForHTML($attributeDisplayNameFunction.apply($attribute))</td>
-                                    <td>
-                                        #foreach ($value in $attribute.values)
-                                            #if ($replaceDollarWithNewline)
-                                                #set ($encodedValue = $encoder.encodeForHTML($value.getDisplayValue()).replaceAll($encoder.encodeForHTML("$"),"<br>"))
-                                            #else
-                                                #set ($encodedValue = $encoder.encodeForHTML($value.getDisplayValue()))
-                                            #end
-                                            #if ($attributeReleaseFlowDescriptor.perAttributeConsentEnabled)
-                                                <label for="$attribute.id"><strong>$encodedValue</strong></label>
-                                            #else
-                                                <strong>$encodedValue</strong>
-                                            #end
-                                            <br>
-                                        #end
-                                    </td>
-                                    <td style="vertical-align: top">
-                                        #if ($attributeReleaseFlowDescriptor.perAttributeConsentEnabled)
-                                            #set ($inputType = "checkbox")
-                                        #else
-                                            #set ($inputType = "hidden")
-                                        #end
-                                        <input id="$attribute.id" type="$inputType" name="_shib_idp_consentIds" value="$encoder.encodeForHTML($attribute.id)" checked>
-                                    </td>
-                                </tr>
-                            #end
-                        </tbody>
-                    </table>
-                </div>
-                #if ($privacyStatementURL)
-                    <p style="margin-top: 10px;">
-                        <a href="$privacyStatementURL">#springMessageText("idp.attribute-release.privacyStatementURLLabel", "Data privacy information of the service")</a>
-                    </p>
-                #end
-                <div style="float:left;">
-                    <p>
-                        #springMessageText("idp.attribute-release.confirmationQuestion", "The information above would be shared with the service if you proceed. Do you agree to release this information to the service every time you access it?")
-                    </p>
-                    #if ($attributeReleaseFlowDescriptor.doNotRememberConsentAllowed || $attributeReleaseFlowDescriptor.globalConsentAllowed)
-                        <div id="generalConsentDiv" style="display: block; background-color: #F6F6F6;border: 1px gray solid; padding: 10px; width: 92%;">
-                        #springMessageText("idp.attribute-release.consentMethod", "Select an information release consent duration:")
-                    #end
-                    #if ($attributeReleaseFlowDescriptor.doNotRememberConsentAllowed)
-                        <p>
-                            <input id="_shib_idp_doNotRememberConsent" type="radio" name="_shib_idp_consentOptions" value="_shib_idp_doNotRememberConsent">
-                            <label for="_shib_idp_doNotRememberConsent">#springMessageText("idp.attribute-release.doNotRememberConsent", "Ask me again at next login")</label>
-                            <ul>
-                                <li>#springMessageText("idp.attribute-release.doNotRememberConsentItem", "I agree to send my information this time.")</li>
-                            </ul>
-                        </p>
-                    #end
-                    #if ($attributeReleaseFlowDescriptor.doNotRememberConsentAllowed || $attributeReleaseFlowDescriptor.globalConsentAllowed)
-                        <p>
-                            <input id="_shib_idp_rememberConsent" type="radio" name="_shib_idp_consentOptions" value="_shib_idp_rememberConsent" checked>
-                            <label for="_shib_idp_rememberConsent">#springMessageText("idp.attribute-release.rememberConsent", "Ask me again if information changes")</label>
-                            <ul>
-                                <li>#springMessageText("idp.attribute-release.rememberConsentItem", "I agree that the same information will be sent automatically to this service in the future.")</li>
-                            </ul>
-                        </p>
-                    #end
-                    #if ($attributeReleaseFlowDescriptor.globalConsentAllowed)
-                        <p>
-                            <input id="_shib_idp_globalConsent" type="radio" name="_shib_idp_consentOptions" value="_shib_idp_globalConsent">
-                            <label for="_shib_idp_globalConsent">#springMessageText("idp.attribute-release.globalConsent", "Do not ask me again")</label>
-                            <ul>
-                                <li>#springMessageText("idp.attribute-release.globalConsentItem", "I agree that <strong>all</strong> of my information will be released to <strong>any</strong> service.")</li>
-                            </ul>
-                        </p>
-                    #end
-                    #if ($attributeReleaseFlowDescriptor.doNotRememberConsentAllowed || $attributeReleaseFlowDescriptor.globalConsentAllowed)
-                        #springMessageText("idp.attribute-release.consentMethodRevoke", "This setting can be revoked at any time with the checkbox on the login page.")
-                        </div>
-                    #end
-                    <p style="text-align: center;">
-                        <input type="submit" name="_eventId_AttributeReleaseRejected" value="#springMessageText("idp.attribute-release.reject", "Reject")" style="margin-right: 30px;">
-                        <input type="submit" name="_eventId_proceed" value="#springMessageText("idp.attribute-release.accept", "Accept")">
-                    </p>
-                </div>
-            </div>
-        </form>
-    </body>
-</html>
diff --git a/views/intercept/expiring-password.vm b/views/intercept/expiring-password.vm
deleted file mode 100644
index 4395844..0000000
--- a/views/intercept/expiring-password.vm
+++ /dev/null
@@ -1,54 +0,0 @@
-##
-## Velocity Template for expiring password view
-##
-## Velocity context will contain the following properties
-## flowExecutionUrl - the form action location
-## flowRequestContext - the Spring Web Flow RequestContext
-## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
-## profileRequestContext - root of context tree
-## authenticationContext - context with authentication request information
-## authenticationErrorContext - context with login error state
-## authenticationWarningContext - context with login warning state
-## ldapResponseContext - context with LDAP state (if using native LDAP)
-## encoder - HTMLEncoder class
-## request - HttpServletRequest
-## response - HttpServletResponse
-## environment - Spring Environment object for property resolution
-## custom - arbitrary object injected by deployer
-##
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        <title>#springMessageText("idp.title", "Web Login Service")</title>
-        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
-        <meta http-equiv="refresh" content="20;url=$flowExecutionUrl&_eventId_proceed=1">
-    </head>
-      
-    <body>
-      <div class="wrapper">
-        <div class="container">
-            <header>
-                <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
-                <h3>#springMessageText("idp.login.expiringSoon", "Your password will be expiring soon!")</h3>
-            </header>
-        
-            <div class="content">
-                <p>#springMessageText("idp.login.changePassword", "To create a new password now, go to")
-                <strong><a href="#" target="_blank">#</a></strong>.</p>
-                <p>#springMessageText("idp.login.proceedBegin", "Your login will proceed in 20 seconds or you may click")
-                <strong><a href="$flowExecutionUrl&_eventId_proceed=1">#springMessageText("idp.login.proceedHere", "here")</a></strong>
-                #springMessageText("idp.login.proceedEnd", "to continue").</p>
-            </div>
-        </div>
-
-        <footer>
-          <div class="container container-footer">
-            <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-          </div>
-        </footer>
-          
-      </div>
-    </body>
-</html>
\ No newline at end of file
diff --git a/views/intercept/impersonate.vm b/views/intercept/impersonate.vm
deleted file mode 100644
index 2bae957..0000000
--- a/views/intercept/impersonate.vm
+++ /dev/null
@@ -1,90 +0,0 @@
-##
-## Velocity Template for expiring password view
-##
-## Velocity context will contain the following properties
-## flowExecutionUrl - the form action location
-## flowRequestContext - the Spring Web Flow RequestContext
-## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
-## profileRequestContext - root of context tree
-## rpUIContext - the context with SP UI information from the metadata
-## encoder - HTMLEncoder class
-## request - HttpServletRequest
-## response - HttpServletResponse
-## environment - Spring Environment object for property resolution
-## custom - arbitrary object injected by deployer
-##
-#set ($rpContext = $profileRequestContext.getSubcontext('net.shibboleth.idp.profile.context.RelyingPartyContext'))
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        <title>#springMessageText("idp.title", "Web Login Service")</title>
-        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
-    </head>
-      
-    <body>
-      <div class="wrapper">
-        <div class="container">
-          <header>
-            <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
-              <h3>#springMessageText("idp.impersonate.header", "Account Impersonation")</h3>
-          </header>
-        
-          <div class="content">
-
-            <form action="$flowExecutionUrl" method="post">
-    
-            #set ($serviceName = $rpUIContext.serviceName)
-            #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
-              <legend>
-                $encoder.encodeForHTML($serviceName)
-              </legend>
-            #end
-
-              <legend>
-                #springMessageText("idp.impersonate.text", "Enter an account name to impersonate to this service or continue normally.")
-              </legend>
-
-              <div class="form-element-wrapper">
-                <label for="impersonation">#springMessageText("idp.impersonate.login-as", "Login as")</label>
-                <input class="form-element form-field" id="impersonation" name="principal" type="text">
-                
-                <!-- Defaults to input box above, example below populates a select list from an IdPAttribute. -->
-                <!--
-                #set ($attributeContext = $rpContext.getSubcontext('net.shibboleth.idp.attribute.context.AttributeContext'))
-                #set ($usernamesAttribute = $attributeContext.getUnfilteredIdPAttributes().get("impersonatableUsernames"))
-                <select class="form-element form-field" id="impersonation" name="principal">
-                #if ($usernamesAttribute)
-                  #foreach ($username in $usernamesAttribute.getValues())
-                    <option value="$encoder.encodeForHTML($username.getValue())">$encoder.encodeForHTML($username.getValue())</option>
-                  #end
-                #end
-                </select>
-                -->
-              </div>
-
-              <div class="form-element-wrapper">
-                <button class="form-element form-button" type="submit" name="_eventId_impersonate"
-                    >#springMessageText("idp.impersonate.impersonate", "Impersonate")</button>
-              </div>
-
-              <div class="form-element-wrapper">
-                <button class="form-element form-button" type="submit" name="_eventId_proceed"
-                    >#springMessageText("idp.impersonate.continue", "Continue Normally")</button>
-              </div>
-                
-            </form>
-
-          </div>
-        </div>
-
-        <footer>
-          <div class="container container-footer">
-            <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-          </div>
-        </footer>
-          
-      </div>
-    </body>
-</html>
\ No newline at end of file
diff --git a/views/intercept/terms-of-use.vm b/views/intercept/terms-of-use.vm
deleted file mode 100644
index 1bf12c7..0000000
--- a/views/intercept/terms-of-use.vm
+++ /dev/null
@@ -1,67 +0,0 @@
-##
-## Velocity Template for DisplayTermsOfUsePage view-state
-##
-## Velocity context will contain the following properties :
-##
-## encoder - HTMLEncoder class
-## flowExecutionKey - SWF execution key (this is built into the flowExecutionUrl)
-## flowExecutionUrl - form action location
-## flowRequestContext - Spring Web Flow RequestContext
-## request - HttpServletRequest
-## response - HttpServletResponse
-## rpUIContext - context with SP UI information from the metadata
-## termsOfUseId - terms of use ID to lookup message strings
-## environment - Spring Environment object for property resolution
-#set ($serviceName = $rpUIContext.serviceName)
-#set ($rpOrganizationLogo = $rpUIContext.getLogo())
-##
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="UTF-8">
-        <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/consent.css">
-        <title>#springMessageText("${termsOfUseId}.title", "Terms of Use")</title>
-    </head>
-    <body>
-        <div class="box">
-            <header>
-                <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")" class="federation_logo">
-                #if ($rpOrganizationLogo)
-                    <img src="$encoder.encodeForHTMLAttribute($rpOrganizationLogo)" alt="$encoder.encodeForHTMLAttribute($serviceName)" class="organization_logo">
-                #end
-            </header>
-            #if ($rpOrganizationLogo)
-                <div style="float:left;">
-                    <h1>#springMessageText("${termsOfUseId}.title", "Terms of Use")</h1>
-                </div>
-            #end
-            <div id="tou-content">
-                #springMessageText("${termsOfUseId}.text", "Terms of Use Text...")
-            </div>
-            <div id="tou-acceptance">
-                <div style="float:left;">
-                    <form action="$flowExecutionUrl" method="post" >
-                        <input type="submit" name="_eventId_TermsRejected" value="#springMessageText("idp.terms-of-use.reject", "Refuse")" style="margin-right: 30px;">
-                    </form>
-                </div>
-                <div style="float:right;">
-                    <form action="$flowExecutionUrl" method="post" >
-                        <input id="accept" type="checkbox" name="_shib_idp_consentIds" value="$encoder.encodeForHTML($termsOfUseId)" required>
-                        <label for="accept">#springMessageText("idp.terms-of-use.accept", "I accept the terms of use")</label>
-                        #if ($requireCheckbox)
-                            <p class="form-error">#springMessageText("idp.terms-of-use.required", "Please check this box if you want to proceed.")</p>
-                        #end
-                        <input type="submit" name="_eventId_proceed" value="#springMessageText("idp.terms-of-use.submit", "Submit")">
-                    </form>
-                </div>
-                <div style="clear:both;"></div>
-            </div>
-            <footer>
-                <div class="container container-footer">
-                    <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-                </div>
-            </footer>
-        </div>
-    </body>
-</html>
diff --git a/views/login-error.vm b/views/login-error.vm
index 44676b3..224976b 100644
--- a/views/login-error.vm
+++ b/views/login-error.vm
@@ -2,11 +2,13 @@
 ##
 ## authenticationErrorContext - context containing error data, if available
 ##
-#if ($authenticationErrorContext && $authenticationErrorContext.getClassifiedErrors().size() > 0 && $authenticationErrorContext.getClassifiedErrors().iterator().next() != "ReselectFlow")
+#if ($authenticationErrorContext && $authenticationErrorContext.getClassifiedErrors().size() > 0)
     ## This handles errors that are classified by the message maps in the authentication config.
     #set ($eventId = $authenticationErrorContext.getClassifiedErrors().iterator().next())
-    #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "login"))
-    #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "Login Failure: $eventId"))
+    #if ($eventId != "ReselectFlow")
+        #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "login"))
+        #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "Login Failure: $eventId"))
+    #end
 #elseif ($authenticationErrorContext && $authenticationErrorContext.getExceptions().size() > 0)
     ## This handles login exceptions that are left unclassified.
     #set ($loginException = $authenticationErrorContext.getExceptions().get(0))
diff --git a/views/login.vm b/views/login.vm
index 4ebf9bf..c7b15c9 100644
--- a/views/login.vm
+++ b/views/login.vm
@@ -46,7 +46,7 @@
             #parse("login-error.vm")
 
             <form action="$flowExecutionUrl" method="post">
-
+            #parse("csrf/csrf.vm")
             #set ($serviceName = $rpUIContext.serviceName)
             #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
               <legend>
@@ -58,12 +58,12 @@
               <div class="form-element-wrapper">
                 <label for="username">#springMessageText("idp.login.username", "Username")</label>
                 <input class="form-element form-field" id="username" name="j_username" type="text"
-                	value="#if($username)$encoder.encodeForHTML($username)#end">
+                    value="#if($username)$encoder.encodeForHTML($username)#end" />
               </div>
 
               <div class="form-element-wrapper">
                 <label for="password">#springMessageText("idp.login.password", "Password")</label>
-                <input class="form-element form-field" id="password" name="j_password" type="password" value="">
+                <input class="form-element form-field" id="password" name="j_password" type="password" value="" />
               </div>
 
               ## You may need to modify this to taste, such as changing the flow name its checking for to authn/MFA.
@@ -77,7 +77,7 @@
             #end
 
               <div class="form-element-wrapper">
-                <input id="_shib_idp_revokeConsent" type="checkbox" name="_shib_idp_revokeConsent" value="true">
+                <input id="_shib_idp_revokeConsent" type="checkbox" name="_shib_idp_revokeConsent" value="true" />
                 <label for="_shib_idp_revokeConsent">#springMessageText("idp.attribute-release.revoke", "Clear prior granting of permission for release of your information to this service.")</label>
               </div>
 
@@ -90,7 +90,7 @@
             #end
 
             #foreach ($extFlow in $extendedAuthenticationFlows)
-              #if ($authenticationContext.isAcceptable($extFlow) and $extFlow.apply(profileRequestContext))
+              #if ($authenticationContext.isAcceptable($extFlow) and $extFlow.test(profileRequestContext))
                 <div class="form-element-wrapper">
                   <button class="form-element form-button" type="submit" name="_eventId_$extFlow.getId()">
                     #springMessageText("idp.login.$extFlow.getId().replace('authn/','')", $extFlow.getId().replace('authn/',''))
@@ -100,7 +100,7 @@
             #end
             </form>
 
-			#*
+            #*
               //
               //    SP Description & Logo (optional)
               //    These idpui lines will display added information (if available
@@ -125,9 +125,9 @@
           <div class="column two">
             <ul class="list list-help">
               #if ($passwordEnabled)
-                <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
+                <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
               #end
-              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
             </ul>
           </div>
         </div>
@@ -140,5 +140,5 @@
       </footer>
     </div>
     
- 	</body>
+     </body>
 </html>
\ No newline at end of file
diff --git a/views/logout-complete.vm b/views/logout-complete.vm
index d780252..7341e69 100644
--- a/views/logout-complete.vm
+++ b/views/logout-complete.vm
@@ -14,6 +14,8 @@
 ## environment - Spring Environment object for property resolution
 ## custom - arbitrary object injected by deployer
 ##
+#set ($activeIdPSessions = $logoutContext and !$logoutContext.getIdPSessions().isEmpty())
+#set ($activeSPSessions = $logoutContext and !$logoutContext.getSessionMap().isEmpty())
 <!DOCTYPE html>
 <html>
     <head>
@@ -32,12 +34,18 @@
 
         <div class="content">
           <div class="column one">
+          #if ($activeIdPSessions)
+            <p>#springMessageText("idp.logout.cancelled", "Logout has been cancelled.")</p>
+          #elseif ($activeSPSessions)
             <p>#springMessageText("idp.logout.local", "You elected not to log out of all the applications accessed during your session.")</p>
+          #else
+            <p>#springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")</p>
+          #end
           </div>
           <div class="column two">
             <ul class="list list-help">
-              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
-              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
             </ul>
           </div>
         </div>
diff --git a/views/logout-propagate.vm b/views/logout-propagate.vm
index 86b3fa1..470eff5 100644
--- a/views/logout-propagate.vm
+++ b/views/logout-propagate.vm
@@ -40,8 +40,8 @@
           </div>
           <div class="column two">
             <ul class="list list-help">
-              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
-              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
             </ul>
           </div>
         </div>
diff --git a/views/logout.vm b/views/logout.vm
index d31ae0e..3d8d50b 100644
--- a/views/logout.vm
+++ b/views/logout.vm
@@ -18,20 +18,24 @@
 #if ($rpContext)
 #set ($rpUIContext = $rpContext.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext"))
 #end
+#set ($promptForIdP = $logoutContext and !$logoutContext.getIdPSessions().isEmpty())
+#set ($promptForSP = $logoutContext and !$logoutContext.getSessionMap().isEmpty())
 <!DOCTYPE html>
 <html>
     <head>
         <meta charset="utf-8">
         <meta name="viewport" content="width=device-width,initial-scale=1.0">
-        #if ( $logoutContext and !$logoutContext.getSessionMap().isEmpty() )
+        #if ($promptForSP)
             <meta http-equiv="refresh" content="10;url=$flowExecutionUrl&_eventId=propagate">
+        #elseif ($promptForIdP)
+            <meta http-equiv="refresh" content="10;url=$flowExecutionUrl&_eventId=local">
         #end
         <title>#springMessageText("idp.title", "Web Login Service")</title>
         <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
     </head>
 
     <body>
-    <div class="wrapper">
+    <div class="wrapper">   
       <div class="container">
         <header>
           <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
@@ -45,30 +49,37 @@
             <br>
     
             #if ($rpContext)
-                <p>#springMessageText("idp.logout.sp-initiated", "You have been logged out of the following service:")</p>
-                <blockquote>
-                #if ($rpUIContext)
-                    $encoder.encodeForHTML($rpUIContext.getServiceName())
-                #else
-                    $encoder.encodeForHTML($rpContext.getRelyingPartyId())
-                #end
-                </blockquote>
-                <br>
+              <p>#springMessageText("idp.logout.sp-initiated", "You have been logged out of the following service:")</p>
+              <blockquote>
+              #if ($rpUIContext)
+                  $encoder.encodeForHTML($rpUIContext.getServiceName())
+              #else
+                  $encoder.encodeForHTML($rpContext.getRelyingPartyId())
+              #end
+              </blockquote>
+              <br>
             #end
+            
+            #if ($promptForIdP or $promptForSP)
+              <p>#springMessageText("idp.logout.prompt", "Choose one of the following, or wait a few seconds for the default.")</p>
+              <br>
 
-            #if ( $logoutContext and !$logoutContext.getSessionMap().isEmpty() )
-                <p>#springMessageText("idp.logout.ask", "Would you like to attempt to log out of all services accessed during your session? Please select <strong>Yes</strong> or <strong>No</strong> to ensure the logout operation completes, or wait a few seconds for Yes.")</p>
-                <br>
-
-                <form id="propagate_form" method="POST" action="$flowExecutionUrl">
-                    <button id="propagate_yes" type="submit" name="_eventId" value="propagate">Yes</button>
-                    <button id="propagate_no" type="submit" name="_eventId" value="end">No</button>
-                </form>
+              <form id="propagate_form" method="POST" action="$flowExecutionUrl">
+                
+                <div class="form-element-wrapper">
+                  <button id="logout_local" class="form-element form-button" type="submit" name="_eventId" value="local">#springMessageText("idp.logout.idponly", "Logout Locally")</button>
+                  <p>#springMessageText("idp.logout.idponly.caption", "End your SSO session.")</p>
+                </div>
+            #end
 
-                <br>
-                <p>#springMessageText("idp.logout.contactServices", "If you proceed, the system will attempt to contact the following services:")</p>
-                <ol>
-                #foreach ($sp in $logoutContext.getSessionMap().keySet())
+            #if ($promptForSP)
+                <div class="form-element-wrapper">
+                  <button id="logout_propagate" class="form-element form-button" type="submit" name="_eventId" value="propagate">#springMessageText("idp.logout.global", "Logout Globally")</button>
+                  <p>#springMessageText("idp.logout.global.caption", "End your SSO session and attempt logout of services accessed during session.")</p>
+                  <br>
+                  <p>#springMessageText("idp.logout.contactServices", "If instructed, the system will attempt to contact the following services:")</p>
+                  <ol>
+                  #foreach ($sp in $logoutContext.getSessionMap().keySet())
                     #set ($rpCtx = $multiRPContext.getRelyingPartyContextById($sp))
                     #if ($rpCtx)
                       #set ($rpUIContext = $rpCtx.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext"))
@@ -78,8 +89,21 @@
                     #else
                       <li>$encoder.encodeForHTML($sp)</li>
                     #end
-                #end
-                </ol>
+                  #end
+                  </ol>
+                  <br>
+                </div>
+            #end
+
+            #if ($promptForIdP)
+                <div class="form-element-wrapper">
+                  <button id="logout_cancel" class="form-element form-button" type="submit" name="_eventId" value="end">#springMessageText("idp.logout.cancel", "Cancel")</button>
+                  <p>#springMessageText("idp.logout.cancel.caption", "Cancel logout and retain your SSO session.")</p>
+                </div>
+            #end
+            
+            #if ($promptForIdP or $promptForSP)
+              </form>
             #else
                 <p><strong>#springMessageText("idp.logout.complete", "The logout operation is complete, and no other services appear to have been accessed during this session.")</strong></p>
                 <!-- Complete the flow by adding a hidden iframe. -->
@@ -89,8 +113,8 @@
           </div>
           <div class="column two">
             <ul class="list list-help">
-              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
-              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", "#")"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
+              <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", '#')"><span class="item-marker">&rsaquo;</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
             </ul>
           </div>
         </div>
@@ -103,5 +127,5 @@
       </footer>
     </div>
     
- 	</body>
+  </body>
 </html>
\ No newline at end of file
diff --git a/views/spnego-unavailable.vm b/views/spnego-unavailable.vm
deleted file mode 100644
index 3673f02..0000000
--- a/views/spnego-unavailable.vm
+++ /dev/null
@@ -1,49 +0,0 @@
-##
-## Velocity Template for SPNEGO unauthorized page
-##
-## This is not a Spring Webflow view, but a special view internal to the
-## SPNEGO login flow, so it doesn't contain all of the usual SWF variables.
-##
-## Velocity context will contain the following properties
-## encoder - HTMLEncoder class
-## request - HttpServletRequest
-## response - HttpServletResponse
-## profileRequestContext - root of context tree
-## errorUrl - URL to call to indicate error and return back to the login flow
-##
-#set ($eventKey = $springMacroRequestContext.getMessage("SPNEGOUnavailable", "spnego-unavailable"))
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width,initial-scale=1.0">
-    <title>#springMessageText("idp.title", "Web Login Sevice") - #springMessageText("${eventKey}.title", "Error")</title>
-    <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
-  </head>
-  
-  <body onload="window.location = '$errorUrl'">
-    <div class="wrapper">
-      <div class="container">
-        <header>
-          <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
-          <h3>#springMessageText("idp.title", "Web Login Sevice") - #springMessage("idp.title.suffix", "Error")</h3>
-        </header>
-                
-        <div class="content">
-          #springMessageText("${eventKey}.message", "Your web browser doesn't support authentication with your desktop login credentials.")
-          <ul class="list list-help">
-            <li class="list-help-item">
-              <a href="$errorUrl"><span class="item-marker">&rsaquo;</span> #springMessageText("spnego-unavailable.return", "Cancel the attempt.")</a>
-            </li>
-          </ul>
-        </div>
-      </div>
-
-      <footer>
-        <div class="container container-footer">
-          <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
-        </div>
-      </footer>
-    </div>
-  </body>
-</html>