From ccf6798e741fc1f83d0c3f6ecfbc48c0d48b560e Mon Sep 17 00:00:00 2001
From: Paul Caskey <pcaskey@internet2.edu>
Date: Thu, 3 Aug 2017 17:37:52 -0500
Subject: [PATCH] initial commit

---
 README.md                                     |   4 +-
 conf/access-control.xml                       |  68 ++++
 conf/admin/general-admin.xml                  |  53 ++++
 conf/admin/metrics.xml                        | 129 ++++++++
 conf/attribute-filter.xml                     |  45 +++
 conf/attribute-resolver-full.xml              | 292 ++++++++++++++++++
 conf/attribute-resolver-ldap.xml              |  94 ++++++
 conf/attribute-resolver.xml                   |  86 ++++++
 conf/audit.xml                                |  32 ++
 conf/authn/authn-comparison.xml               |  77 +++++
 conf/authn/authn-events-flow.xml              |  21 ++
 conf/authn/duo-authn-config.xml               |  25 ++
 conf/authn/duo.properties                     |   9 +
 conf/authn/external-authn-config.xml          |  70 +++++
 conf/authn/general-authn.xml                  | 156 ++++++++++
 conf/authn/ipaddress-authn-config.xml         |  37 +++
 conf/authn/jaas-authn-config.xml              |  27 ++
 conf/authn/jaas.config                        |  11 +
 conf/authn/krb5-authn-config.xml              |  31 ++
 conf/authn/ldap-authn-config.xml              | 135 ++++++++
 conf/authn/mfa-authn-config.xml               |  99 ++++++
 conf/authn/password-authn-config.xml          | 121 ++++++++
 conf/authn/remoteuser-authn-config.xml        |  75 +++++
 .../remoteuser-internal-authn-config.xml      |  63 ++++
 conf/authn/spnego-authn-config.xml            |  74 +++++
 conf/authn/x509-authn-config.xml              |  44 +++
 conf/authn/x509-internal-authn-config.xml     |  21 ++
 .../attribute-sourced-subject-c14n-config.xml |  44 +++
 conf/c14n/simple-subject-c14n-config.xml      |  27 ++
 conf/c14n/subject-c14n-events-flow.xml        |  22 ++
 conf/c14n/subject-c14n.xml                    | 109 +++++++
 conf/c14n/x500-subject-c14n-config.xml        |  37 +++
 conf/cas-protocol.xml                         |  84 +++++
 conf/credentials.xml                          |  65 ++++
 conf/errors.xml                               | 120 +++++++
 conf/global.xml                               |  53 ++++
 conf/idp.properties                           | 195 ++++++++++++
 conf/intercept/consent-intercept-config.xml   | 136 ++++++++
 .../context-check-intercept-config.xml        |  42 +++
 .../expiring-password-intercept-config.xml    |  37 +++
 conf/intercept/intercept-events-flow.xml      |  21 ++
 conf/intercept/profile-intercept.xml          |  38 +++
 conf/ldap.properties                          |  63 ++++
 conf/logback.xml                              | 186 +++++++++++
 conf/metadata-providers.xml                   |  67 ++++
 conf/mvc-beans.xml                            |  23 ++
 conf/relying-party.xml                        |  70 +++++
 conf/saml-nameid.properties                   |  35 +++
 conf/saml-nameid.xml                          |  62 ++++
 conf/services.properties                      |  65 ++++
 conf/services.xml                             | 144 +++++++++
 conf/session-manager.xml                      |  45 +++
 credentials/idp-backchannel.crt               |  20 ++
 credentials/idp-backchannel.p12               | Bin 0 -> 2596 bytes
 credentials/idp-encryption.crt                |  20 ++
 credentials/idp-encryption.key                |  27 ++
 credentials/idp-signing.crt                   |  20 ++
 credentials/idp-signing.key                   |  27 ++
 credentials/idp-userfacing.p12                | Bin 0 -> 2596 bytes
 credentials/sealer.jks                        | Bin 0 -> 500 bytes
 credentials/sealer.kver                       |   2 +
 edit-webapp/css/consent.css                   | 150 +++++++++
 edit-webapp/css/logout.css                    |  12 +
 edit-webapp/css/main.css                      | 165 ++++++++++
 edit-webapp/images/dummylogo-mobile.png       | Bin 0 -> 8208 bytes
 edit-webapp/images/dummylogo.png              | Bin 0 -> 13742 bytes
 edit-webapp/images/failure-32x32.png          | Bin 0 -> 2580 bytes
 edit-webapp/images/success-32x32.png          | Bin 0 -> 2448 bytes
 messages/messages.properties                  |   2 +
 metadata/idp-metadata.xml                     | 219 +++++++++++++
 views/client-storage/client-storage-read.vm   |  53 ++++
 views/client-storage/client-storage-write.vm  |  53 ++++
 views/duo.vm                                  |  83 +++++
 views/error.vm                                |  73 +++++
 views/intercept/attribute-release.vm          | 158 ++++++++++
 views/intercept/expiring-password.vm          |  54 ++++
 views/intercept/terms-of-use.vm               |  67 ++++
 views/login-error.vm                          |  24 ++
 views/login.vm                                | 140 +++++++++
 views/logout-complete.vm                      |  59 ++++
 views/logout-propagate.vm                     |  58 ++++
 views/logout.vm                               |  91 ++++++
 views/spnego-unavailable.vm                   |  49 +++
 views/user-prefs.js                           |  45 +++
 views/user-prefs.vm                           |  60 ++++
 85 files changed, 5418 insertions(+), 2 deletions(-)
 create mode 100644 conf/access-control.xml
 create mode 100644 conf/admin/general-admin.xml
 create mode 100644 conf/admin/metrics.xml
 create mode 100644 conf/attribute-filter.xml
 create mode 100644 conf/attribute-resolver-full.xml
 create mode 100644 conf/attribute-resolver-ldap.xml
 create mode 100644 conf/attribute-resolver.xml
 create mode 100644 conf/audit.xml
 create mode 100644 conf/authn/authn-comparison.xml
 create mode 100644 conf/authn/authn-events-flow.xml
 create mode 100644 conf/authn/duo-authn-config.xml
 create mode 100644 conf/authn/duo.properties
 create mode 100644 conf/authn/external-authn-config.xml
 create mode 100644 conf/authn/general-authn.xml
 create mode 100644 conf/authn/ipaddress-authn-config.xml
 create mode 100644 conf/authn/jaas-authn-config.xml
 create mode 100644 conf/authn/jaas.config
 create mode 100644 conf/authn/krb5-authn-config.xml
 create mode 100644 conf/authn/ldap-authn-config.xml
 create mode 100644 conf/authn/mfa-authn-config.xml
 create mode 100644 conf/authn/password-authn-config.xml
 create mode 100644 conf/authn/remoteuser-authn-config.xml
 create mode 100644 conf/authn/remoteuser-internal-authn-config.xml
 create mode 100644 conf/authn/spnego-authn-config.xml
 create mode 100644 conf/authn/x509-authn-config.xml
 create mode 100644 conf/authn/x509-internal-authn-config.xml
 create mode 100644 conf/c14n/attribute-sourced-subject-c14n-config.xml
 create mode 100644 conf/c14n/simple-subject-c14n-config.xml
 create mode 100644 conf/c14n/subject-c14n-events-flow.xml
 create mode 100644 conf/c14n/subject-c14n.xml
 create mode 100644 conf/c14n/x500-subject-c14n-config.xml
 create mode 100644 conf/cas-protocol.xml
 create mode 100644 conf/credentials.xml
 create mode 100644 conf/errors.xml
 create mode 100644 conf/global.xml
 create mode 100644 conf/idp.properties
 create mode 100644 conf/intercept/consent-intercept-config.xml
 create mode 100644 conf/intercept/context-check-intercept-config.xml
 create mode 100644 conf/intercept/expiring-password-intercept-config.xml
 create mode 100644 conf/intercept/intercept-events-flow.xml
 create mode 100644 conf/intercept/profile-intercept.xml
 create mode 100644 conf/ldap.properties
 create mode 100644 conf/logback.xml
 create mode 100644 conf/metadata-providers.xml
 create mode 100644 conf/mvc-beans.xml
 create mode 100644 conf/relying-party.xml
 create mode 100644 conf/saml-nameid.properties
 create mode 100644 conf/saml-nameid.xml
 create mode 100644 conf/services.properties
 create mode 100644 conf/services.xml
 create mode 100644 conf/session-manager.xml
 create mode 100644 credentials/idp-backchannel.crt
 create mode 100644 credentials/idp-backchannel.p12
 create mode 100644 credentials/idp-encryption.crt
 create mode 100644 credentials/idp-encryption.key
 create mode 100644 credentials/idp-signing.crt
 create mode 100644 credentials/idp-signing.key
 create mode 100644 credentials/idp-userfacing.p12
 create mode 100644 credentials/sealer.jks
 create mode 100644 credentials/sealer.kver
 create mode 100644 edit-webapp/css/consent.css
 create mode 100644 edit-webapp/css/logout.css
 create mode 100644 edit-webapp/css/main.css
 create mode 100644 edit-webapp/images/dummylogo-mobile.png
 create mode 100644 edit-webapp/images/dummylogo.png
 create mode 100644 edit-webapp/images/failure-32x32.png
 create mode 100644 edit-webapp/images/success-32x32.png
 create mode 100644 messages/messages.properties
 create mode 100644 metadata/idp-metadata.xml
 create mode 100644 views/client-storage/client-storage-read.vm
 create mode 100644 views/client-storage/client-storage-write.vm
 create mode 100644 views/duo.vm
 create mode 100644 views/error.vm
 create mode 100644 views/intercept/attribute-release.vm
 create mode 100644 views/intercept/expiring-password.vm
 create mode 100644 views/intercept/terms-of-use.vm
 create mode 100644 views/login-error.vm
 create mode 100644 views/login.vm
 create mode 100644 views/logout-complete.vm
 create mode 100644 views/logout-propagate.vm
 create mode 100644 views/logout.vm
 create mode 100644 views/spnego-unavailable.vm
 create mode 100644 views/user-prefs.js
 create mode 100644 views/user-prefs.vm

diff --git a/README.md b/README.md
index f26284c..84ef433 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 ## Purpose
 
-This project contains the configuration tree (structure) for Shibboleth IDP.  The are various usage scenarios throughout the build, test, deploy cycle that warrant this abstraction
+This project contains the configuration tree (structure) for Shibboleth IDP on Windows.  The are various usage scenarios throughout the build, test, deploy cycle that warrant this abstraction
 of the configuration tree.  There is a separate repository for the Docker Image which is responsible for building the runtime environment and pulling the configuration trees housed here
 to complete a deployment.
 
@@ -11,4 +11,4 @@ to complete a deployment.
   * `test` branch
     * 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
+    * External Testing - (RELEASE) branch/repo
\ No newline at end of file
diff --git a/conf/access-control.xml b/conf/access-control.xml
new file mode 100644
index 0000000..a9184e6
--- /dev/null
+++ b/conf/access-control.xml
@@ -0,0 +1,68 @@
+<?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">
+
+    <!--
+    Map of access control policies used to limit access to administrative functions.
+    The purpose of the map is to label policies with a key/name so they can be reused.
+    -->
+
+    <!--
+    Use the "shibboleth.IPRangeAccessControl" parent bean for IP-based access control.
+    The ranges provided MUST be CIDR network expressions. To specify a single address,
+    add "/32" or "/128" for IPv4 or IPv6 respectively.
+
+    The additional examples below demonstrate how to control access by username
+    and by attribute(s), in the case of authenticated access to admin functions.
+    -->
+
+    <util:map id="shibboleth.AccessControlPolicies">
+    
+        <entry key="AccessByIPAddress">
+            <bean id="AccessByIPAddress" parent="shibboleth.IPRangeAccessControl"
+                p:allowedRanges="#{ {'127.0.0.1/32', '::1/128'} }" />
+        </entry>
+        
+        <!--
+        <entry key="AccessByUser">
+            <bean parent="shibboleth.PredicateAccessControl">
+                <constructor-arg>
+                    <bean parent="shibboleth.Conditions.SubjectName" c:collection="#{'jdoe'}" />
+                </constructor-arg>
+            </bean>
+        </entry>
+        -->
+        
+        <!--
+        <entry key="AccessByAttribute">
+            <bean parent="shibboleth.PredicateAccessControl">
+                <constructor-arg>
+                    <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate">
+                        <property name="attributeValueMap">
+                            <map>
+                                <entry key="eduPersonEntitlement">
+                                    <list>
+                                        <value>https://example.org/entitlement/idpadmin</value>
+                                    </list>
+                                </entry>
+                            </map>
+                        </property>
+                    </bean>
+                </constructor-arg>
+            </bean>
+        </entry>
+        -->
+    
+    </util:map>
+
+</beans>
diff --git a/conf/admin/general-admin.xml b/conf/admin/general-admin.xml
new file mode 100644
index 0000000..9b3b180
--- /dev/null
+++ b/conf/admin/general-admin.xml
@@ -0,0 +1,53 @@
+<?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}" />
+
+        <!-- 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" />
+    
+    </util:list>
+
+</beans>
diff --git a/conf/admin/metrics.xml b/conf/admin/metrics.xml
new file mode 100644
index 0000000..f9b5c16
--- /dev/null
+++ b/conf/admin/metrics.xml
@@ -0,0 +1,129 @@
+<?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">
+    
+    <!-- Metrics enablement / activation. -->
+
+    <!--
+    Register one or more of the built-in system metric sets available.
+    -->
+
+    <bean parent="shibboleth.metrics.RegisterMetricSets">
+        <property name="arguments">
+            <list>
+                <ref bean="shibboleth.metrics.CoreGaugeSet" />
+                <ref bean="shibboleth.metrics.IdPGaugeSet" />
+                <ref bean="shibboleth.metrics.LoggingGaugeSet" />
+                <ref bean="shibboleth.metrics.AccessControlGaugeSet" />
+                <ref bean="shibboleth.metrics.MetadataGaugeSet" />
+                <ref bean="shibboleth.metrics.NameIdentifierGaugeSet" />
+                <ref bean="shibboleth.metrics.RelyingPartyGaugeSet" />
+                <ref bean="shibboleth.metrics.AttributeResolverGaugeSet" />
+                <ref bean="shibboleth.metrics.AttributeFilterGaugeSet" />
+
+                <!--
+                <bean class="com.codahale.metrics.jvm.CachedThreadStatesGaugeSet"
+                    c:_0="1" c:_1="#{T(java.util.concurrent.TimeUnit).MINUTES}" />
+                <bean class="com.codahale.metrics.jvm.ClassLoadingGaugeSet" />
+                <bean class="com.codahale.metrics.jvm.GarbageCollectorMetricSet" />
+                <bean class="com.codahale.metrics.jvm.MemoryUsageGaugeSet" />
+                -->
+            </list>
+        </property>
+    </bean>
+
+    <!-- Metrics REST API Configuration -->
+
+    <!--
+    The global metric set is available by default at /idp/profile/admin/metrics
+    
+    Any pathinfo after that is assumed to identify specific named metrics. You can
+    create mappings here between a logical "group" name and an implementation of the
+    com.codahale.metrics.MetricFilter interface to specify which metrics to include.
+    -->
+    <util:map id="shibboleth.metrics.MetricGroups">
+        <entry key="core" value-ref="shibboleth.metrics.CoreGaugeSet" />
+        <entry key="idp" value-ref="shibboleth.metrics.IdPGaugeSet" />
+        <entry key="logging" value-ref="shibboleth.metrics.LoggingGaugeSet" />
+        <entry key="access" value-ref="shibboleth.metrics.AccessControlGaugeSet" />
+        <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="resolver" value-ref="shibboleth.metrics.AttributeResolverGaugeSet" />
+        <entry key="filter" value-ref="shibboleth.metrics.AttributeFilterGaugeSet" />
+    </util:map>
+        
+    <!-- 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" />
+    
+    <!--
+    To override the default access policy, map a metric name or
+    mapped group above to an alternative policy name.
+    -->
+    <util:map id="shibboleth.metrics.AccessPolicyMap">
+    
+    </util:map>
+        
+    <!--
+    In addition to the "pull" REST API for accessing metrics, a "push" reporter is also
+    available to upload a JSON feed to a URL. The example shown relies on standard JVM
+    trust configuration for TLS server verification.
+    
+    The "start" method triggers the timer thread; the example pushes every 30 minutes.
+    -->
+    <!--
+    <bean id="PushReporter" parent="shibboleth.metrics.HTTPReporter" c:name="MyCollector"
+        p:collectorURL="https://log.example.org/cgi-bin/collector.cgi" />
+                
+    <bean class="org.springframework.beans.factory.config.MethodInvokingBean"
+            p:targetObject-ref="PushReporter"
+            p:targetMethod="start">
+        <property name="arguments">
+            <list>
+                <value>30</value>
+                <util:constant static-field="java.util.concurrent.TimeUnit.MINUTES" />
+            </list>
+        </property>
+    </bean>
+    -->
+
+    <!-- IdP Metrics Configuration -->
+    
+    <!--
+    A bean named shibboleth.metrics.MetricStrategy of type Function<ProfileRequestContext,Boolean>
+    can be defined to add timers and counters to a large range of objects in the system. Each timer is
+    defined by a triple (timer name, start object, stop object). Counters are just object/counter pairs.
+    
+    The most common example is to start a timer when a particular flow action bean starts and
+    stop it when the same or different action bean stops, to measure how long the execution takes.
+    
+    If you want to leave a timer in place but disabled to prevent overhead, you can turn off a
+    logging category named "metrics.<timername>" in your logging configuration.
+    -->
+    <!--
+    <bean id="shibboleth.metrics.MetricStrategy" parent="shibboleth.ContextFunctions.Scripted"
+            factory-method="inlineScript">
+        <constructor-arg>
+            <value>
+            <![CDATA[
+                metricCtx = input.getSubcontext("org.opensaml.profile.context.MetricContext");
+                metricCtx.addTimer("idp.attribute.resolution",
+                    "ResolveAttributes",
+                    "FilterAttributes"
+                    );                                
+                true; // Signals success.
+            ]]>
+            </value>
+        </constructor-arg>
+    </bean>
+    -->
+    
+</beans>
diff --git a/conf/attribute-filter.xml b/conf/attribute-filter.xml
new file mode 100644
index 0000000..f8c41ba
--- /dev/null
+++ b/conf/attribute-filter.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+    This file is an EXAMPLE policy file.  While the policy presented in this 
+    example file is illustrative of some simple cases, it relies on the names of
+    non-existent example services and the example attributes demonstrated in the
+    default attribute-resolver.xml file.
+    
+    Deployers should refer to the documentation for a complete list of components
+    and their options.
+-->
+<AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
+        xmlns="urn:mace:shibboleth:2.0:afp"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">
+
+    <!-- Release some attributes to an SP. -->
+    <AttributeFilterPolicy id="example1">
+        <PolicyRequirementRule xsi:type="Requester" value="https://sp.example.org" />
+
+        <AttributeRule attributeID="eduPersonPrincipalName">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+
+        <AttributeRule attributeID="uid">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+
+        <AttributeRule attributeID="mail">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+    <!-- Release eduPersonAffiliation to two specific SPs. -->
+    <AttributeFilterPolicy id="example2">
+        <PolicyRequirementRule xsi:type="OR">
+            <Rule xsi:type="Requester" value="https://sp.example.org" />
+            <Rule xsi:type="Requester" value="https://another.example.org/shibboleth" />
+        </PolicyRequirementRule>
+
+        <AttributeRule attributeID="eduPersonScopedAffiliation">
+            <PermitValueRule xsi:type="ANY" />
+        </AttributeRule>
+    </AttributeFilterPolicy>
+
+</AttributeFilterPolicyGroup>
diff --git a/conf/attribute-resolver-full.xml b/conf/attribute-resolver-full.xml
new file mode 100644
index 0000000..4681b64
--- /dev/null
+++ b/conf/attribute-resolver-full.xml
@@ -0,0 +1,292 @@
+<?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:sec="urn:mace:shibboleth:2.0:security"
+        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
+                            urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd">
+
+    <!-- ========================================== -->
+    <!--      Attribute Definitions                 -->
+    <!-- ========================================== -->
+
+    <!-- Schema: Core schema attributes-->
+<!--
+    <AttributeDefinition xsi:type="Simple" id="uid" sourceAttributeID="uid">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="mail">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="homePhone">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="homePostalAddress">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="mobile">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="pager">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="sn">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="l">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="st">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="street">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="o">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="ou">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="title">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="postalAddress">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="postalCode">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="postOfficeBox">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="telephoneNumber">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="givenName">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="initials">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="departmentNumber">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="displayName">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="employeeNumber">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="employeeType">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="jpegPhoto">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="preferredLanguage">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonAffiliation">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonEntitlement">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonNickname">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonPrimaryAffiliation">
+        <Dependency ref="myLDAP" />
+        <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="Scoped" id="eduPersonUniqueId" scope="%{idp.scope}" sourceAttributeID="localUniqueId">
+        <Dependency ref="myLDAP" />
+        <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>
+
+    <AttributeDefinition xsi:type="Prescoped" id="eduPersonPrincipalName" sourceAttributeID="eduPersonPrincipalName">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonPrincipalNamePrior">
+        <Dependency ref="myLDAP" />
+        <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}" sourceAttributeID="eduPersonAffiliation">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="eduPersonAssurance">
+        <Dependency ref="myLDAP" />
+        <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>
+-->
+
+    <!-- ========================================== -->
+    <!--      Data Connectors                       -->
+    <!-- ========================================== -->
+
+    <!-- Example Static Connector -->
+<!--
+    <DataConnector id="staticAttributes" xsi:type="Static">
+        <Attribute id="eduPersonAffiliation">
+            <Value>member</Value>
+        </Attribute>
+    </DataConnector>
+-->
+
+    <!-- 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}"
+        responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}">
+        <FilterTemplate>
+            <![CDATA[
+                %{idp.attribute.resolver.LDAP.searchFilter}
+            ]]>
+        </FilterTemplate>
+        <StartTLSTrustCredential id="LDAPtoIdPCredential" xsi:type="sec:X509ResourceBacked">
+            <sec:Certificate>%{idp.attribute.resolver.LDAP.trustCertificates}</sec:Certificate>
+        </StartTLSTrustCredential>
+    </DataConnector>
+-->
+
+</AttributeResolver>
diff --git a/conf/attribute-resolver-ldap.xml b/conf/attribute-resolver-ldap.xml
new file mode 100644
index 0000000..ec79de9
--- /dev/null
+++ b/conf/attribute-resolver-ldap.xml
@@ -0,0 +1,94 @@
+<?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" sourceAttributeID="eduPersonPrincipalName">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="uid">
+        <Dependency ref="myLDAP" />
+        <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" sourceAttributeID="mail">
+        <Dependency ref="myLDAP" />
+        <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
new file mode 100644
index 0000000..d752e07
--- /dev/null
+++ b/conf/attribute-resolver.xml
@@ -0,0 +1,86 @@
+<?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.
+
+    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="Scoped" scope="%{idp.scope}" sourceAttributeID="uid">
+        <Dependency 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>
+
+    <!--
+    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="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>
+
+    <!--
+    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="Template">
+        <Dependency 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>
+
+    <!--
+    This is an example of an attribute sourced from a data connector.
+    -->
+    <AttributeDefinition id="eduPersonScopedAffiliation" xsi:type="Scoped" scope="%{idp.scope}" sourceAttributeID="affiliation">
+        <Dependency ref="staticAttributes" />
+        <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>
+
+
+    <!-- ========================================== -->
+    <!--      Data Connectors                       -->
+    <!-- ========================================== -->
+
+    <DataConnector id="staticAttributes" xsi:type="Static">
+        <Attribute id="affiliation">
+            <Value>member</Value>
+        </Attribute>
+    </DataConnector>
+
+</AttributeResolver>
diff --git a/conf/audit.xml b/conf/audit.xml
new file mode 100644
index 0000000..22949fd
--- /dev/null
+++ b/conf/audit.xml
@@ -0,0 +1,32 @@
+<?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 bean defines a mapping between audit log categories and formatting strings. The default entry is
+    for compatibility with V2 audit logging.
+    -->
+    <util:map id="shibboleth.AuditFormattingMap">
+        <entry key="Shibboleth-Audit" value="%T|%b|%I|%SP|%P|%IDP|%bb|%III|%u|%ac|%attr|%n|%i|" />
+    </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" />
+    <util:constant id="shibboleth.AuditDefaultTimeZone" static-field="java.lang.Boolean.TRUE" />
+    -->
+
+    <!-- Allows auditing to be disabled selectively for particular profiles/flows. -->
+    <util:list id="shibboleth.AuditSuppressedProfiles">
+        <value>http://shibboleth.net/ns/profiles/status</value>
+    </util:list>
+
+</beans>
diff --git a/conf/authn/authn-comparison.xml b/conf/authn/authn-comparison.xml
new file mode 100644
index 0000000..f167b7a
--- /dev/null
+++ b/conf/authn/authn-comparison.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       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">
+
+    <!--
+    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.
+    -->
+    
+    <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" />
+
+    <!-- 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. -->
+    
+    <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>
+    
+</beans>
diff --git a/conf/authn/authn-events-flow.xml b/conf/authn/authn-events-flow.xml
new file mode 100644
index 0000000..36d62a1
--- /dev/null
+++ b/conf/authn/authn-events-flow.xml
@@ -0,0 +1,21 @@
+<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">
+
+    <!-- ADVANCED USE ONLY -->
+    
+    <!--
+    You can ignore this file unless you are creating your own custom login subflows that want to
+    report custom events in response to unusual error or warning conditions.
+    -->
+
+    <!-- Custom error events to reflect back from user-supplied login subflows. -->
+    <!--
+    <end-state id="MyCustomEvent" />
+
+    <global-transitions>
+        <transition on="MyCustomEvent" to="MyCustomEvent" />
+    </global-transitions>
+    -->
+</flow>
diff --git a/conf/authn/duo-authn-config.xml b/conf/authn/duo-authn-config.xml
new file mode 100644
index 0000000..0a48152
--- /dev/null
+++ b/conf/authn/duo-authn-config.xml
@@ -0,0 +1,25 @@
+<?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 a statically-defined integration 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.
+
+    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.
+    -->
+
+</beans>
diff --git a/conf/authn/duo.properties b/conf/authn/duo.properties
new file mode 100644
index 0000000..2ca71ee
--- /dev/null
+++ b/conf/authn/duo.properties
@@ -0,0 +1,9 @@
+# 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.
+
+idp.duo.apiHost = hostname
+idp.duo.applicationKey = key
+idp.duo.integrationKey = key
+idp.duo.secretKey = key
diff --git a/conf/authn/external-authn-config.xml b/conf/authn/external-authn-config.xml
new file mode 100644
index 0000000..8b3a159
--- /dev/null
+++ b/conf/authn/external-authn-config.xml
@@ -0,0 +1,70 @@
+<?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/general-authn.xml b/conf/authn/general-authn.xml
new file mode 100644
index 0000000..ac55bbb
--- /dev/null
+++ b/conf/authn/general-authn.xml
@@ -0,0 +1,156 @@
+<?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/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
new file mode 100644
index 0000000..a3ee096
--- /dev/null
+++ b/conf/authn/ipaddress-authn-config.xml
@@ -0,0 +1,37 @@
+<?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
new file mode 100644
index 0000000..daef4d2
--- /dev/null
+++ b/conf/authn/jaas-authn-config.xml
@@ -0,0 +1,27 @@
+<?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
new file mode 100644
index 0000000..232e93d
--- /dev/null
+++ b/conf/authn/jaas.config
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 0000000..d3590a2
--- /dev/null
+++ b/conf/authn/krb5-authn-config.xml
@@ -0,0 +1,31 @@
+<?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
new file mode 100644
index 0000000..56d1bc7
--- /dev/null
+++ b/conf/authn/ldap-authn-config.xml
@@ -0,0 +1,135 @@
+<?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
new file mode 100644
index 0000000..ef3b80e
--- /dev/null
+++ b/conf/authn/mfa-authn-config.xml
@@ -0,0 +1,99 @@
+<?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);
+
+                    // 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
new file mode 100644
index 0000000..f27051b
--- /dev/null
+++ b/conf/authn/password-authn-config.xml
@@ -0,0 +1,121 @@
+<?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">
+    
+    <!-- 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" />
+    
+    
+    <!-- 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"/>
+
+    <!-- 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" />
+        -->
+    </util:list>
+    
+    <!-- Uncomment to configure account lockout backed by in-memory storage. -->
+    <!--
+    <bean id="shibboleth.authn.Password.AccountLockoutManager"
+        parent="shibboleth.StorageBackedAccountLockoutManager"
+        p:maxAttempts="5"
+        p:counterInterval="PT5M"
+        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.
+
+    Keys are events to signal, values are error codes.
+    -->
+    <util:map id="shibboleth.authn.Password.ClassifiedMessageMap">
+        <entry key="UnknownUsername">
+            <list>
+                <value>NoCredentials</value>
+                <value>CLIENT_NOT_FOUND</value>
+                <value>Client not found</value>
+                <value>DN_RESOLUTION_FAILURE</value>
+            </list>
+        </entry>
+        <entry key="InvalidPassword">
+            <list>
+                <value>InvalidCredentials</value>
+                <value>PREAUTH_FAILED</value>
+                <value>INVALID_CREDENTIALS</value>
+                <value>Checksum failed</value>
+            </list>
+        </entry>
+        <entry key="AccountLocked">
+            <list>
+                <value>AccountLocked</value>
+                <value>Clients credentials have been revoked</value>
+            </list>
+        </entry>
+        <entry key="ExpiredPassword">
+            <list>
+                <value>PASSWORD_EXPIRED</value>
+            </list>
+        </entry>
+        <entry key="ExpiringPassword">
+            <list>
+                <value>ACCOUNT_WARNING</value>
+            </list>
+        </entry>
+    </util:map>
+
+    <!--
+    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
+    must also be enabled at the "top" level to be available for use.
+    
+    The ExtendedFlowParameters bean can be used to transfer custom parameters from the
+    login form into the context tree for use later by other flows.
+    
+    The last bean provides the set of custom Principals to use for results produced by the
+    Password flow itself. You would use this if you need the Password flow to run as a shell
+    to run the "extended" login methods, but want to limit its own results more narrowly.
+    -->
+    <!--
+    <bean id="shibboleth.authn.Password.ExtendedFlows" class="java.lang.String" c:_0="" />
+
+    <util:list id="shibboleth.authn.Password.ExtendedFlowParameters">
+    </util:list>
+
+    <util:list id="shibboleth.authn.Password.PrincipalOverride">
+        <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" />
+    </util:list>
+    -->
+    
+</beans>
diff --git a/conf/authn/remoteuser-authn-config.xml b/conf/authn/remoteuser-authn-config.xml
new file mode 100644
index 0000000..4b7e722
--- /dev/null
+++ b/conf/authn/remoteuser-authn-config.xml
@@ -0,0 +1,75 @@
+<?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
new file mode 100644
index 0000000..9e68c85
--- /dev/null
+++ b/conf/authn/remoteuser-internal-authn-config.xml
@@ -0,0 +1,63 @@
+<?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
new file mode 100644
index 0000000..07563b9
--- /dev/null
+++ b/conf/authn/spnego-authn-config.xml
@@ -0,0 +1,74 @@
+<?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
new file mode 100644
index 0000000..18b015a
--- /dev/null
+++ b/conf/authn/x509-authn-config.xml
@@ -0,0 +1,44 @@
+<?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/authn/x509-internal-authn-config.xml b/conf/authn/x509-internal-authn-config.xml
new file mode 100644
index 0000000..bad3029
--- /dev/null
+++ b/conf/authn/x509-internal-authn-config.xml
@@ -0,0 +1,21 @@
+<?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">
+
+    <!--
+    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.
+    -->
+    
+</beans>
diff --git a/conf/c14n/attribute-sourced-subject-c14n-config.xml b/conf/c14n/attribute-sourced-subject-c14n-config.xml
new file mode 100644
index 0000000..938b30f
--- /dev/null
+++ b/conf/c14n/attribute-sourced-subject-c14n-config.xml
@@ -0,0 +1,44 @@
+<?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
new file mode 100644
index 0000000..3cddfa6
--- /dev/null
+++ b/conf/c14n/simple-subject-c14n-config.xml
@@ -0,0 +1,27 @@
+<?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-events-flow.xml b/conf/c14n/subject-c14n-events-flow.xml
new file mode 100644
index 0000000..c8e7220
--- /dev/null
+++ b/conf/c14n/subject-c14n-events-flow.xml
@@ -0,0 +1,22 @@
+<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">
+
+    <!-- ADVANCED USE ONLY -->
+    
+    <!--
+    You can ignore this file unless you are creating your own custom c14n subflows that want to
+    report custom events in response to unusual error or warning conditions.
+    -->
+
+    <!-- Custom error events to reflect back from user-supplied c14n subflows. -->
+    <!--
+    <end-state id="MyCustomEvent" />
+
+    <global-transitions>
+        <transition on="MyCustomEvent" to="MyCustomEvent" />
+    </global-transitions>
+    -->
+
+</flow>
diff --git a/conf/c14n/subject-c14n.xml b/conf/c14n/subject-c14n.xml
new file mode 100644
index 0000000..16fc6f1
--- /dev/null
+++ b/conf/c14n/subject-c14n.xml
@@ -0,0 +1,109 @@
+<?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">
+    
+    <!-- ========================= Java Subject -> Principal Mapping ========================= -->
+
+    <!--
+    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. 
+    Flows are identified with an ID that corresponds to a Spring Web Flow subflow 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. 
+        -->
+        <!-- <bean id="c14n/attribute" parent="shibboleth.PostLoginSubjectCanonicalizationFlow" /> -->
+
+        <!--
+        This is an alternative that handles Subjects containing an X500Principal object and
+        allows extraction from the DN.
+        -->
+        <ref bean="c14n/x500" />
+
+        <!--
+        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
+        -->
+        <ref bean="c14n/simple" />
+    </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.
+    -->
+    <util:list id="shibboleth.SAMLSubjectCanonicalizationFlows">
+
+        <!--
+        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.
+        -->
+        <ref bean="c14n/LegacyPrincipalConnector" />
+        
+        <!-- The next four are for handling transient IDs (in-storage and stateless variants). -->
+        <ref bean="c14n/SAML2Transient" />
+        <ref bean="c14n/SAML2CryptoTransient" />
+        <ref bean="c14n/SAML1Transient" /> 
+        <ref bean="c14n/SAML1CryptoTransient" /> 
+        
+        <!-- Handle a SAML 2 persistent ID, provided a stored strategy is in use. -->
+        <!-- <ref bean="c14n/SAML2Persistent" /> -->
+        
+        <!--
+        Finally we have beans for decoding arbitrary SAML formats directly. By default, these are turned off,
+        having *no* circumstances for which they apply (see shibboleth.TransformNamePredicate below).
+        -->
+        <ref bean="c14n/SAML2Transform" />
+        <ref bean="c14n/SAML1Transform" />
+    </util:list>
+    
+    <!-- What SAML NameID formats do you want to support direct transformations for? -->
+    <util:list id="shibboleth.NameTransformFormats">
+        <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>
+
+    <!--
+    Under what conditions should direct NameID mapping be allowed? By default, never.
+    Any condition can be used here; the example is suitable for enumerating a number of SPs to allow.
+    -->
+    <bean id="shibboleth.NameTransformPredicate" parent="shibboleth.Conditions.RelyingPartyId">
+        <constructor-arg>
+            <list>
+                <!-- <value>https://sp.example.org</value> -->
+            </list>
+        </constructor-arg>
+    </bean>
+    
+    <!--
+    Regular expression transforms to apply to incoming subject names. The default empty list just
+    echoes the name through unmodified.
+    -->
+    <util:list id="shibboleth.NameTransforms">
+        <!--
+        <bean parent="shibboleth.Pair" p:first="^(.+)@example\.edu$" p:second="$1" />
+        -->
+    </util:list>
+    
+</beans>
diff --git a/conf/c14n/x500-subject-c14n-config.xml b/conf/c14n/x500-subject-c14n-config.xml
new file mode 100644
index 0000000..1ae25e4
--- /dev/null
+++ b/conf/c14n/x500-subject-c14n-config.xml
@@ -0,0 +1,37 @@
+<?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
new file mode 100644
index 0000000..d0b3d55
--- /dev/null
+++ b/conf/cas-protocol.xml
@@ -0,0 +1,84 @@
+<?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"
+       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>
+
+    <!--
+       | 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" />
+
+
+    <!-- ============== Advanced CAS Configuration ============== -->
+
+    <!-- Configure a third-party ticket service. -->
+    <!--
+    <bean id="shibboleth.CASTicketService"
+          class="org.example.idp.cas.CustomTicketService" />
+    -->
+
+    <!-- Configure a third-party proxy authenticator. -->
+    <!--
+    <bean id="shibboleth.CASProxyAuthenticator"
+          class="org.example.idp.cas.CustomProxyAuthenticator" />
+    -->
+</beans>
\ No newline at end of file
diff --git a/conf/credentials.xml b/conf/credentials.xml
new file mode 100644
index 0000000..7462879
--- /dev/null
+++ b/conf/credentials.xml
@@ -0,0 +1,65 @@
+<?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">
+
+    <!--
+    NOTE: if you're using a legacy relying-party.xml file from a V2 configuration, this file is ignored.
+
+    This defines the signing and encryption key and certificate pairs referenced by your relying-party.xml
+    configuration. You don't normally need to touch this, unless you have advanced requirements such as
+    supporting multiple sets of keys for different relying parties, in which case you may want to define
+    all your credentials here for convenience.
+    -->
+
+    <!--
+    The list of ALL of your IdP's signing credentials. If you define additional signing credentials,
+    for example for specific relying parties or different key types, make sure to include them within this list.
+    -->
+    <util:list id="shibboleth.SigningCredentials">
+        <ref bean="shibboleth.DefaultSigningCredential" />
+    </util:list>
+    
+    <!-- Your IdP's default signing key, set via property file. -->
+    <bean id="shibboleth.DefaultSigningCredential"
+        class="net.shibboleth.idp.profile.spring.factory.BasicX509CredentialFactoryBean"
+        p:privateKeyResource="%{idp.signing.key}"
+        p:certificateResource="%{idp.signing.cert}"
+        p:entityId-ref="entityID" />
+        
+    <!--
+    The list of ALL of your IdP's encryption credentials. By default this is just an alias
+    for 'shibboleth.DefaultEncryptionCredentials'. It could be re-defined as
+    a list with additional credentials if needed.
+    -->
+    <alias alias="shibboleth.EncryptionCredentials" name="shibboleth.DefaultEncryptionCredentials" />
+        
+    <!-- Your IdP's default encryption (really decryption) keys, set via property file. -->
+    <util:list id="shibboleth.DefaultEncryptionCredentials">
+        <bean class="net.shibboleth.idp.profile.spring.factory.BasicX509CredentialFactoryBean"
+            p:privateKeyResource="%{idp.encryption.key}"
+            p:certificateResource="%{idp.encryption.cert}"
+            p:entityId-ref="entityID" />
+
+        <!--
+        For key rollover, uncomment and point to your original keypair, and use the one above
+        to point to your new keypair. Once metadata has propagated, comment this one out again.
+        -->
+        <!--
+        <bean class="net.shibboleth.idp.profile.spring.factory.BasicX509CredentialFactoryBean"
+            p:privateKeyResource="%{idp.encryption.key.2}"
+            p:certificateResource="%{idp.encryption.cert.2}"
+            p:entityId-ref="entityID" />
+        -->
+    </util:list>
+
+</beans>
diff --git a/conf/errors.xml b/conf/errors.xml
new file mode 100644
index 0000000..5de522f
--- /dev/null
+++ b/conf/errors.xml
@@ -0,0 +1,120 @@
+<?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 id="shibboleth.DefaultErrorView" class="java.lang.String" c:_0="%{idp.errors.defaultView:error}" />
+
+    <!-- Map local events to alternate view templates. -->
+    <util:map id="shibboleth.EventViewMap">
+        <!-- <entry key="EventToChange" value="viewname" /> -->
+    </util:map>
+
+    <!--
+    Map of events to trap and handle with local views, without returning to SPs.
+    The map values are flags indicating whether to write an audit log record.
+    -->
+    <util:map id="shibboleth.LocalEventMap">
+        <entry key="ContextCheckDenied" value="true" />
+        <entry key="AttributeReleaseRejected" value="true" />
+        <entry key="TermsRejected" value="true" />
+        <entry key="RuntimeException" value="false" />
+        <!--
+        <entry key="IdentitySwitch" value="false" />
+        <entry key="NoPotentialFlow" value="false" />
+        -->
+    </util:map>
+    
+    <!-- Mappings of error events during requests to SAML status codes and SOAP fault codes. -->
+
+    <util:map id="shibboleth.SAML1StatusMappings">
+        <entry key="InvalidMessageVersion" value-ref="shibboleth.SAML1Status.VersionMismatch" />
+        
+        <entry key="UnableToDecode" value-ref="shibboleth.SAML1Status.Requester" />
+        
+        <entry key="UnableToEncode" value-ref="shibboleth.SAML1Status.Requester" />
+
+        <entry key="MessageReplay" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="MessageExpired" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="MessageAuthenticationError" value-ref="shibboleth.SAML1Status.Requester" />
+
+        <entry key="RequestUnsupported" value-ref="shibboleth.SAML1Status.Requester" />
+        
+        <entry key="NoPassive" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="NoPotentialFlow" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="NoCredentials" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="InvalidCredentials" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="AccountError" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="IdentitySwitch" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="AuthenticationException" value-ref="shibboleth.SAML1Status.Requester" />
+        
+        <entry key="InvalidSubject" value-ref="shibboleth.SAML1Status.Requester" />
+        <entry key="SubjectCanonicalizationError" value-ref="shibboleth.SAML1Status.Requester" />
+    </util:map>
+    
+    <util:map id="shibboleth.SAML2StatusMappings">
+        <entry key="InvalidMessageVersion" value-ref="shibboleth.SAML2Status.VersionMismatch" />
+        
+        <entry key="UnableToDecode" value-ref="shibboleth.SAML2Status.RequestUnsupported" />
+        
+        <entry key="UnableToEncode" value-ref="shibboleth.SAML2Status.UnsupportedBinding" />
+
+        <entry key="MessageReplay" value-ref="shibboleth.SAML2Status.RequestDenied" />
+        <entry key="MessageExpired" value-ref="shibboleth.SAML2Status.RequestDenied" />
+        <entry key="MessageAuthenticationError" value-ref="shibboleth.SAML2Status.RequestDenied" />
+        
+        <entry key="RequestUnsupported" value-ref="shibboleth.SAML2Status.NoAuthnContext" />
+        
+        <entry key="NoPassive" value-ref="shibboleth.SAML2Status.NoPassive" />
+        
+        <entry key="NoPotentialFlow" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        <entry key="NoCredentials" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        <entry key="InvalidCredentials" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        <entry key="AccountError" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        <entry key="IdentitySwitch" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        <entry key="AuthenticationException" value-ref="shibboleth.SAML2Status.AuthnFailed" />
+        
+        <entry key="InvalidSubject" value-ref="shibboleth.SAML2Status.UnknownPrincipal" />
+        <entry key="SubjectCanonicalizationError" value-ref="shibboleth.SAML2Status.UnknownPrincipal" />
+        <entry key="SessionNotFound" value-ref="shibboleth.SAML2Status.UnknownPrincipal" />
+        
+        <entry key="InvalidNameIDPolicy" value-ref="shibboleth.SAML2Status.InvalidNameIDPolicy" />
+        
+        <entry key="ChannelBindingsError" value-ref="shibboleth.SAML2Status.ChannelBindingsError" />
+    </util:map>
+
+    <util:map id="shibboleth.SOAPFaultCodeMappings">
+        <entry key="InvalidMessageVersion" value-ref="shibboleth.SOAP.VersionMismatch" />
+        
+        <entry key="UnableToDecode" value-ref="shibboleth.SOAP.Client" />
+
+        <entry key="MessageReplay" value-ref="shibboleth.SOAP.Client" />
+        <entry key="MessageExpired" value-ref="shibboleth.SOAP.Client" />
+        <entry key="MessageAuthenticationError" value-ref="shibboleth.SOAP.Client" />
+        
+        <entry key="RequestUnsupported" value-ref="shibboleth.SOAP.Client" />
+    
+        <entry key="NoPassive" value-ref="shibboleth.SOAP.Client" />
+        
+        <entry key="NoPotentialFlow" value-ref="shibboleth.SOAP.Client" />
+        <entry key="NoCredentials" value-ref="shibboleth.SOAP.Client" />
+        <entry key="InvalidCredentials" value-ref="shibboleth.SOAP.Client" />
+        <entry key="AccountError" value-ref="shibboleth.SOAP.Client" />
+        <entry key="AuthenticationException" value-ref="shibboleth.SOAP.Client" />
+
+        <entry key="InvalidSubject" value-ref="shibboleth.SOAP.Client" />
+        <entry key="SubjectCanonicalizationError" value-ref="shibboleth.SOAP.Client" />
+        
+        <entry key="InvalidNameIDPolicy" value-ref="shibboleth.SOAP.Client" />
+        
+        <entry key="ChannelBindingsError" value-ref="shibboleth.SOAP.Client" />
+    </util:map>
+    
+</beans>
diff --git a/conf/global.xml b/conf/global.xml
new file mode 100644
index 0000000..60562e3
--- /dev/null
+++ b/conf/global.xml
@@ -0,0 +1,53 @@
+<?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">
+
+    <!-- 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.
+    -->
+    
+    <!--
+    <util:list id="shibboleth.SignatureWhitelist">
+    </util:list>
+
+    <util:list id="shibboleth.SignatureBlacklist">
+    </util:list>
+
+    <util:list id="shibboleth.EncryptionWhitelist">
+    </util:list>
+
+    <util:list id="shibboleth.EncryptionBlacklist">
+    </util:list>
+    -->
+
+    <!--
+    If you need to define and inject custom Java object(s) into the various views used throughout the
+    system (errors, login, logout, etc.), you can uncomment and define the bean below to be of any
+    type required. It will appear in the view scope as a variable named "custom".
+    
+    The example below defines the bean as a map, which allows you to inject multiple objects under
+    named keys to expand the feature to support multiple injected objects.
+    -->
+    
+    <!--
+    <util:map id="shibboleth.CustomViewContext">
+        <entry key="foo" value="bar"/>
+    </util:map>
+    -->
+    
+    
+</beans>
diff --git a/conf/idp.properties b/conf/idp.properties
new file mode 100644
index 0000000..1a77f4a
--- /dev/null
+++ b/conf/idp.properties
@@ -0,0 +1,195 @@
+# 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
+
+# Set the entityID of the IdP
+idp.entityID= https://shibboleth.example.org/idp/shibboleth
+
+# Set the scope used in the attribute resolver for scoped attributes
+idp.scope= example.org
+
+# General cookie properties (maxAge only applies to persistent cookies)
+#idp.cookie.secure = false
+#idp.cookie.httpOnly = true
+#idp.cookie.domain =
+#idp.cookie.path =
+#idp.cookie.maxAge = 31536000
+
+# Set the location of user-supplied web flow definitions
+#idp.webflows = %{idp.home}/flows
+
+# Set the location of Velocity view templates
+#idp.views = %{idp.home}/views
+
+# Settings for internal AES encryption key
+#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= password
+idp.sealer.keyPassword= password
+
+# Settings for public/private signing and encryption key(s)
+# During decryption key rollover, point the ".2" properties at a second
+# keypair, uncomment in credentials.xml, then publish it in your metadata.
+idp.signing.key= %{idp.home}/credentials/idp-signing.key
+idp.signing.cert= %{idp.home}/credentials/idp-signing.crt
+idp.encryption.key= %{idp.home}/credentials/idp-encryption.key
+idp.encryption.cert= %{idp.home}/credentials/idp-encryption.crt
+#idp.encryption.key.2 = %{idp.home}/credentials/idp-encryption-old.key
+#idp.encryption.cert.2 = %{idp.home}/credentials/idp-encryption-old.crt
+
+# Sets the bean ID to use as a default security configuration set
+#idp.security.config = shibboleth.DefaultSecurityConfiguration
+
+# To default to SHA-1, set to shibboleth.SigningConfiguration.SHA1
+#idp.signing.config = shibboleth.SigningConfiguration.SHA256
+
+# 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
+
+# If true, encryption will happen whenever a key to use can be located, but
+# failure to encrypt won't result in request failure.
+#idp.encryption.optional = false
+
+# Configuration of client- and server-side storage plugins
+#idp.storage.cleanupInterval = PT10M
+#idp.storage.htmlLocalStorage = false
+
+# Set to true to expose more detailed errors in responses to SPs
+#idp.errors.detailed = false
+# Set to false to skip signing of SAML response messages that signal errors
+#idp.errors.signed = true
+# Name of bean containing a list of Java exception classes to ignore
+#idp.errors.excludedExceptions = ExceptionClassListBean
+# Name of bean containing a property set mapping exception names to views
+#idp.errors.exceptionMappings = ExceptionToViewPropertyBean
+# Set if a different default view name for events and exceptions is needed
+#idp.errors.defaultView = error
+
+# Set to false to disable the IdP session layer
+#idp.session.enabled = true
+
+# Set to "shibboleth.StorageService" for server-side storage of user sessions
+#idp.session.StorageService = shibboleth.ClientSessionStorageService
+
+# Size of session IDs
+#idp.session.idSize = 32
+# Bind sessions to IP addresses
+#idp.session.consistentAddress = true
+# Inactivity timeout
+#idp.session.timeout = PT60M
+# Extra time to store sessions for logout
+#idp.session.slop = PT0S
+# Tolerate storage-related errors
+#idp.session.maskStorageFailure = false
+# Track information about SPs logged into
+#idp.session.trackSPSessions = false
+# Support lookup by SP for SAML logout
+#idp.session.secondaryServiceIndex = false
+# 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
+
+# Regular expression of forced "initial" methods when no session exists,
+# usually in conjunction with the idp.authn.resolveAttribute property below.
+#idp.authn.flows.initial = Password
+
+# Set to an attribute ID to resolve prior to selecting authentication flows;
+# its values are used to filter the flows to allow.
+#idp.authn.resolveAttribute = eduPersonAssurance
+
+# 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
+
+# Set to "shibboleth.consent.AttributeConsentStorageKey" to use an attribute
+# to key user consent storage records (and set the attribute name)
+#idp.consent.userStorageKey = shibboleth.consent.PrincipalConsentStorageKey
+#idp.consent.userStorageKeyAttribute = uid
+
+# Flags controlling how built-in attribute consent feature operates
+#idp.consent.allowDoNotRemember = true
+#idp.consent.allowGlobal = true
+#idp.consent.allowPerAttribute = false
+
+# Whether attribute values and terms of use text are compared
+#idp.consent.compareValues = false
+# Maximum number of consent records for space-limited storage (e.g. cookies)
+#idp.consent.maxStoredRecords = 10
+# Maximum number of consent records for larger/server-side storage (0 = no limit)
+#idp.consent.expandedMaxStoredRecords = 0
+
+# Time in milliseconds to expire consent storage records.
+#idp.consent.storageRecordLifetime = P1Y
+
+# Whether to lookup metadata, etc. for every SP involved in a logout
+# for use by user interface logic; adds overhead so off by default.
+#idp.logout.elaboration = false
+
+# Whether to require logout requests/responses be signed/authenticated.
+#idp.logout.authenticated = true
+
+# Message freshness and replay cache tuning
+#idp.policy.messageLifetime = PT3M
+#idp.policy.clockSkew = PT3M
+
+# Set to custom bean for alternate storage of replay cache
+#idp.replayCache.StorageService = shibboleth.StorageService
+
+# Toggles whether to allow outbound messages via SAML artifact
+#idp.artifact.enabled = true
+# Suppresses typical signing/encryption when artifact binding used
+#idp.artifact.secureChannel = true
+# May differ to direct SAML 2 artifact lookups to specific server nodes
+#idp.artifact.endpointIndex = 2
+# Set to custom bean for alternate storage of artifact map state
+#idp.artifact.StorageService = shibboleth.StorageService
+
+# Comma-delimited languages to use if not match can be found with the
+# browser-supported languages, defaults to an empty list.
+idp.ui.fallbackLanguages= en,fr,de
+
+# Storage service used by CAS protocol
+# 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
+
+# Profile flows in which the ProfileRequestContext should be exposed
+# in servlet request under the key "opensamlProfileRequestContext"
+#idp.profile.exposeProfileRequestContextInServletRequest = SAML2/POST/SSO,SAML2/Redirect/SSO
+
+# 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
diff --git a/conf/intercept/consent-intercept-config.xml b/conf/intercept/consent-intercept-config.xml
new file mode 100644
index 0000000..ca183a7
--- /dev/null
+++ b/conf/intercept/consent-intercept-config.xml
@@ -0,0 +1,136 @@
+<?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>
+
+    <!--
+    The beans below need to be defined, even if left empty. They can be ignored in most cases.
+    
+    If you write your own function to extract a new piece of data for auditing, you can install it into one or more
+    of the maps below to add it to the auditing framework, keyed by an audit field label to be used in formatting.
+    -->
+    <bean id="shibboleth.consent.PreConsentAuditExtractors" parent="shibboleth.consent.DefaultPreConsentAuditExtractors" lazy-init="true">
+        <property name="sourceMap">
+            <map merge="true">
+            </map>
+        </property>
+    </bean>
+
+    <bean id="shibboleth.consent.ConsentAuditExtractors" parent="shibboleth.consent.DefaultConsentAuditExtractors" lazy-init="true">
+        <property name="sourceMap">
+            <map merge="true">
+            </map>
+        </property>
+    </bean>
+
+    <!--
+    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>
+
+</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
new file mode 100644
index 0000000..809f1d4
--- /dev/null
+++ b/conf/intercept/context-check-intercept-config.xml
@@ -0,0 +1,42 @@
+<?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>
+
+</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
new file mode 100644
index 0000000..5447b16
--- /dev/null
+++ b/conf/intercept/expiring-password-intercept-config.xml
@@ -0,0 +1,37 @@
+<?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" p:resultIfMissing="true">
+        <constructor-arg name="formatter">
+            <bean class="org.joda.time.format.DateTimeFormat" factory-method="forPattern" c:_0="yyyyMMddHHmmss'T'" />
+        </constructor-arg>
+        <property name="systemTimeOffset">
+            <bean class="org.joda.time.Duration" factory-method="standardDays" c:_0="-14" />
+        </property>
+    </bean>
+    
+    <!-- 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/intercept-events-flow.xml b/conf/intercept/intercept-events-flow.xml
new file mode 100644
index 0000000..315c258
--- /dev/null
+++ b/conf/intercept/intercept-events-flow.xml
@@ -0,0 +1,21 @@
+<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">
+
+    <!-- ADVANCED USE ONLY -->
+    
+    <!--
+    You can ignore this file unless you are creating your own custom intercept subflows that want to
+    report custom events in response to unusual conditions.
+    -->
+
+    <!--
+    <end-state id="MyCustomEvent" />
+
+    <global-transitions>
+        <transition on="MyCustomEvent" to="MyCustomEvent" />
+    </global-transitions>
+    -->
+
+</flow>
diff --git a/conf/intercept/profile-intercept.xml b/conf/intercept/profile-intercept.xml
new file mode 100644
index 0000000..4040a10
--- /dev/null
+++ b/conf/intercept/profile-intercept.xml
@@ -0,0 +1,38 @@
+<?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" />
+            </list>
+        </property>
+    </bean>
+
+</beans>
diff --git a/conf/ldap.properties b/conf/ldap.properties
new file mode 100644
index 0000000..37b270e
--- /dev/null
+++ b/conf/ldap.properties
@@ -0,0 +1,63 @@
+# LDAP authentication configuration, see authn/ldap-authn-config.xml
+# Note, this doesn't apply to the use of JAAS
+
+## Authenticator strategy, either anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
+#idp.authn.LDAP.authenticator                   = anonSearchAuthenticator
+
+## 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
+
+## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
+#idp.authn.LDAP.sslConfig                       = certificateTrust
+## If using certificateTrust above, set to the trusted certificate's path
+idp.authn.LDAP.trustCertificates                = %{idp.home}/credentials/ldap-server.crt
+## If using keyStoreTrust above, set to the truststore path
+idp.authn.LDAP.trustStore                       = %{idp.home}/credentials/ldap-server.truststore
+
+## Return attributes during authentication
+idp.authn.LDAP.returnAttributes                 = passwordExpirationTime,loginGraceRemaining
+
+## DN resolution properties ##
+
+# Search DN resolution, used by anonSearchAuthenticator, bindSearchAuthenticator
+# for AD: CN=Users,DC=example,DC=org
+idp.authn.LDAP.baseDN                           = ou=people,dc=example,dc=org
+#idp.authn.LDAP.subtreeSearch                   = false
+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
+
+# 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.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)
+
+# LDAP pool configuration, used for both authn and DN resolution
+#idp.pool.LDAP.minSize                          = 3
+#idp.pool.LDAP.maxSize                          = 10
+#idp.pool.LDAP.validateOnCheckout               = false
+#idp.pool.LDAP.validatePeriodically             = true
+#idp.pool.LDAP.validatePeriod                   = PT5M
+#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
new file mode 100644
index 0000000..104ec4c
--- /dev/null
+++ b/conf/logback.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <!--
+    Variables for simplifying logging configuration.
+    http://logback.qos.ch/manual/configuration.html#variableSubstitution
+    -->
+    
+    <variable name="idp.logfiles" value="${idp.home}/logs" />
+    <variable name="idp.loghistory" value="180" />
+    
+    <!-- Much higher performance if you operate on DEBUG. -->
+    <!-- <variable name="idp.process.appender" value="ASYNC_PROCESS" /> -->
+    
+    <!-- Logging level shortcuts. -->
+    <variable name="idp.loglevel.idp" value="INFO" />
+    <variable name="idp.loglevel.ldap" value="WARN" />
+    <variable name="idp.loglevel.messages" value="INFO" />
+    <variable name="idp.loglevel.encryption" value="INFO" />
+    <variable name="idp.loglevel.opensaml" value="INFO" />
+    <variable name="idp.loglevel.props" value="INFO" />
+    
+    <!-- Don't turn these up unless you want a *lot* of noise. -->
+    <variable name="idp.loglevel.spring" value="ERROR" />
+    <variable name="idp.loglevel.container" value="ERROR" />
+    <variable name="idp.loglevel.xmlsec" value="INFO" />
+
+    <!--
+    If you want to use custom properties in this config file,
+    we load the main property file for you.
+    -->
+    <variable file="${idp.home}/conf/idp.properties" />
+    
+    <!-- =========================================================== -->
+    <!-- ============== Logging Categories and Levels ============== -->
+    <!-- =========================================================== -->
+
+    <!-- Logs IdP, but not OpenSAML, messages -->
+    <logger name="net.shibboleth.idp" level="${idp.loglevel.idp:-INFO}"/>
+
+    <!-- Logs OpenSAML, but not IdP, messages -->
+    <logger name="org.opensaml.saml" level="${idp.loglevel.opensaml:-INFO}"/>
+    
+    <!-- Logs LDAP related messages -->
+    <logger name="org.ldaptive" level="${idp.loglevel.ldap:-WARN}"/>
+    
+    <!-- Logs inbound and outbound protocols messages at DEBUG level -->
+    <logger name="PROTOCOL_MESSAGE" level="${idp.loglevel.messages:-INFO}" />
+
+    <!-- Logs unencrypted SAML at DEBUG level -->
+    <logger name="org.opensaml.saml.saml2.encryption.Encrypter" level="${idp.loglevel.encryption:-INFO}" />
+
+    <!-- Logs system properties during startup at DEBUG level -->
+    <logger name="net.shibboleth.idp.log.LogbackLoggingService" level="${idp.loglevel.props:-INFO}" />
+
+    <!-- Especially chatty. -->
+    <logger name="net.shibboleth.idp.saml.attribute.mapping" level="INFO" />
+    <logger name="org.apache.xml.security" level="${idp.loglevel.xmlsec:-INFO}" />
+    <logger name="org.springframework" level="${idp.loglevel.spring:-ERROR}"/>
+    <logger name="org.apache.catalina" level="${idp.loglevel.container:-ERROR}"/>
+    <logger name="org.eclipse.jetty" level="${idp.loglevel.container:-ERROR}"/>
+
+
+    <!-- =========================================================== -->
+    <!-- ============== Low Level Details or Changes =============== -->
+    <!-- =========================================================== -->
+    
+    <!-- Process log. -->
+    <appender name="IDP_PROCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>${idp.logfiles}/idp-process.log</File>
+        
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${idp.logfiles}/idp-process-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>${idp.loghistory:-180}</maxHistory>
+        </rollingPolicy>
+
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>UTF-8</charset>
+            <Pattern>%date{ISO8601} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+        </encoder>
+
+        <!-- Ignore Velocity status page error. -->
+        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+            <evaluator>
+                <matcher>
+                    <Name>VelocityStatusMatcher</Name>
+                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                </matcher>
+                <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+            </evaluator>
+            <OnMatch>DENY</OnMatch>
+        </filter>
+    </appender>
+
+    <appender name="ASYNC_PROCESS" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="IDP_PROCESS" />
+        <discardingThreshold>0</discardingThreshold>
+    </appender>
+
+    <appender name="IDP_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- Suppress anything below WARN. -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>WARN</level>
+        </filter>
+        
+        <File>${idp.logfiles}/idp-warn.log</File>
+        
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${idp.logfiles}/idp-warn-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>${idp.loghistory:-180}</maxHistory>
+        </rollingPolicy>
+        
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>UTF-8</charset>
+            <Pattern>%date{ISO8601} - %level [%logger:%line] - %msg%n%ex{short}</Pattern>
+        </encoder>
+        
+        <!-- Ignore Velocity status page error. -->
+        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+            <evaluator>
+                <matcher>
+                    <Name>VelocityStatusMatcher</Name>
+                    <regex>ResourceManager : unable to find resource 'status.vm' in any resource loader.</regex>
+                </matcher>
+                <expression>VelocityStatusMatcher.matches(formattedMessage)</expression>
+            </evaluator>
+            <OnMatch>DENY</OnMatch>
+        </filter>
+    </appender>
+    
+    <!-- Audit log. -->
+    <appender name="IDP_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>${idp.logfiles}/idp-audit.log</File>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${idp.logfiles}/idp-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>${idp.loghistory:-180}</maxHistory>
+        </rollingPolicy>
+
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>UTF-8</charset>
+            <Pattern>%msg%n</Pattern>
+        </encoder>
+    </appender>
+    
+    <!-- Consent audit log. -->
+    <appender name="IDP_CONSENT_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <File>${idp.logfiles}/idp-consent-audit.log</File>
+
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${idp.logfiles}/idp-consent-audit-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
+            <maxHistory>${idp.loghistory:-180}</maxHistory>
+        </rollingPolicy>
+
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>UTF-8</charset>
+            <Pattern>%msg%n</Pattern>
+        </encoder>
+    </appender>
+
+    <!-- F-TICKS syslog destination. -->
+    <appender name="IDP_FTICKS" class="ch.qos.logback.classic.net.SyslogAppender">
+        <syslogHost>${idp.fticks.loghost:-localhost}</syslogHost>
+        <port>${idp.fticks.logport:-514}</port>
+        <facility>AUTH</facility>
+        <suffixPattern>[%thread] %logger %msg</suffixPattern>
+    </appender>
+
+    <logger name="Shibboleth-Audit" level="ALL">
+        <appender-ref ref="${idp.audit.appender:-IDP_AUDIT}"/>
+    </logger>
+
+    <logger name="Shibboleth-FTICKS" level="ALL" additivity="false">
+        <appender-ref ref="${idp.fticks.appender:-IDP_FTICKS}"/>
+    </logger>
+
+    <logger name="Shibboleth-Consent-Audit" level="ALL">
+        <appender-ref ref="${idp.consent.appender:-IDP_CONSENT_AUDIT}"/>
+    </logger>
+    
+    <root level="${idp.loglevel.root:-INFO}">
+        <appender-ref ref="${idp.process.appender:-IDP_PROCESS}"/>
+        <appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
+    </root>
+
+</configuration>
\ No newline at end of file
diff --git a/conf/metadata-providers.xml b/conf/metadata-providers.xml
new file mode 100644
index 0000000..facc296
--- /dev/null
+++ b/conf/metadata-providers.xml
@@ -0,0 +1,67 @@
+<?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:md="urn:oasis:names:tc:SAML:2.0:metadata"
+    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.                            -->
+    <!-- ========================================================================================== -->
+
+    <!--
+    Example HTTP metadata provider.  Use this if you want to download the metadata
+    from a remote source.
+
+    You *MUST* provide the SignatureValidationFilter in order to function securely.
+    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. 
+    -->
+    
+    <!--
+    <MetadataProvider id="HTTPMetadata"
+                      xsi:type="FileBackedHTTPMetadataProvider"
+                      backingFile="%{idp.home}/metadata/localCopyFromXYZHTTP.xml"
+                      metadataURL="http://WHATEVER"> 
+        
+        <MetadataFilter xsi:type="SignatureValidation" certificateFile="%{idp.home}/credentials/metaroot.pem" />
+        <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D"/>
+        <MetadataFilter xsi:type="EntityRoleWhiteList">
+            <RetainedRole>md:SPSSODescriptor</RetainedRole>
+        </MetadataFilter>
+    </MetadataProvider>
+    -->   
+
+    <!--
+    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.
+    
+    If you do not provide a SignatureValidation filter, then you have the
+    responsibility to ensure that the contents on disk are trustworthy.
+    -->
+    
+    <!--
+    <MetadataProvider id="LocalMetadata"  xsi:type="FilesystemMetadataProvider" metadataFile="PATH_TO_YOUR_METADATA"/>
+    -->
+          
+    
+</MetadataProvider>
diff --git a/conf/mvc-beans.xml b/conf/mvc-beans.xml
new file mode 100644
index 0000000..98d9bcd
--- /dev/null
+++ b/conf/mvc-beans.xml
@@ -0,0 +1,23 @@
+<?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: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:mvc="http://www.springframework.org/schema/mvc"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.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">
+
+    <!--
+    Use this file to define any custom MVC beans needed. Its contents are imported
+    by system/conf/mvc-beans.xml, which configures a lot of the low-level Spring Web
+    behavior of the IdP. You can ignore this file otherwise.
+    -->
+    
+</beans>
diff --git a/conf/relying-party.xml b/conf/relying-party.xml
new file mode 100644
index 0000000..28c9193
--- /dev/null
+++ b/conf/relying-party.xml
@@ -0,0 +1,70 @@
+<?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">
+
+    <!--
+    Unverified RP configuration, defaults to no support for any profiles. Add <ref> elements to the list
+    to enable specific default profile settings (as below), or create new beans inline to override defaults.
+    
+    "Unverified" typically means the IdP has no metadata, or equivalent way of assuring the identity and
+    legitimacy of a requesting system. To run an "open" IdP, you can enable profiles here.
+    -->
+    <bean id="shibboleth.UnverifiedRelyingParty" parent="RelyingParty">
+        <property name="profileConfigurations">
+            <list>
+            <!-- <bean parent="SAML2.SSO" p:encryptAssertions="false" /> -->
+            </list>
+        </property>
+    </bean>
+
+    <!--
+    Default configuration, with default settings applied for all profiles, and enables
+    the attribute-release consent flow.
+    -->
+    <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
+        <property name="profileConfigurations">
+            <list>
+                <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" />
+                <ref bean="SAML1.AttributeQuery" />
+                <ref bean="SAML1.ArtifactResolution" />
+                <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" />
+                <ref bean="SAML2.ECP" />
+                <ref bean="SAML2.Logout" />
+                <ref bean="SAML2.AttributeQuery" />
+                <ref bean="SAML2.ArtifactResolution" />
+                <ref bean="Liberty.SSOS" />
+            </list>
+        </property>
+    </bean>
+
+    <!-- Container for any overrides you want to add. -->
+
+    <util:list id="shibboleth.RelyingPartyOverrides">
+    
+        <!--
+        Override example that identifies a single RP by name and configures it
+        for SAML 2 SSO without encryption. This is a common "vendor" scenario.
+        -->
+        <!--
+        <bean parent="RelyingPartyByName" c:relyingPartyIds="https://sp.example.org">
+            <property name="profileConfigurations">
+                <list>
+                    <bean parent="SAML2.SSO" p:encryptAssertions="false" />
+                </list>
+            </property>
+        </bean>
+        -->
+        
+    </util:list>
+
+</beans>
diff --git a/conf/saml-nameid.properties b/conf/saml-nameid.properties
new file mode 100644
index 0000000..8530c4f
--- /dev/null
+++ b/conf/saml-nameid.properties
@@ -0,0 +1,35 @@
+# Properties involving SAML NameIdentifier/NameID generation/consumption
+
+# For the most part these settings only deal with "transient" and "persistent"
+# 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
+#idp.nameid.saml1.default = urn:mace:shibboleth:1.0:nameIdentifier
+
+# Set to shibboleth.StoredTransientIdGenerator for server-side transient ID storage
+#idp.transientId.generator = shibboleth.CryptoTransientIdGenerator
+
+# 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:
+#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
+
+# To use a database, use shibboleth.StoredPersistentIdGenerator
+#idp.persistentId.generator = shibboleth.ComputedPersistentIdGenerator
+# For basic use, set this to a JDBC DataSource bean name:
+#idp.persistentId.dataSource = PersistentIdDataSource
+# For advanced use, set to a bean inherited from shibboleth.JDBCPersistentIdStore
+#idp.persistentId.store = MyPersistentIdStore
+# Set to an empty property to skip hash-based generation of first stored ID
+#idp.persistentId.computed = shibboleth.ComputedPersistentIdGenerator
diff --git a/conf/saml-nameid.xml b/conf/saml-nameid.xml
new file mode 100644
index 0000000..ea97448
--- /dev/null
+++ b/conf/saml-nameid.xml
@@ -0,0 +1,62 @@
+<?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">
+
+    <!-- ========================= SAML NameID Generation ========================= -->
+
+    <!--
+    These generator lists handle NameID/Nameidentifier generation going forward. By default,
+    transient IDs for both SAML versions are enabled. The commented examples are for persistent IDs
+    and generating more one-off formats based on resolved attributes. The suggested approach is to
+    control their use via release of the underlying source attribute in the filter policy rather
+    than here, but you can set a property on any generator called "activationCondition" to limit
+    use in the most generic way.
+    
+    Most of the relevant configuration settings are controlled using properties; an exception is
+    the generation of arbitrary/custom formats based on attribute information, examples of which
+    are shown below.
+    
+    -->
+    
+    <!-- SAML 2 NameID Generation -->
+    <util:list id="shibboleth.SAML2NameIDGenerators">
+    
+        <ref bean="shibboleth.SAML2TransientGenerator" />
+        
+        <!-- Uncommenting this bean requires configuration in saml-nameid.properties. -->
+        <!--
+        <ref bean="shibboleth.SAML2PersistentGenerator" />
+        -->
+
+        <!--
+        <bean parent="shibboleth.SAML2AttributeSourcedGenerator"
+            p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
+            p:attributeSourceIds="#{ {'mail'} }" />
+        -->
+                
+    </util:list>
+
+    <!-- SAML 1 NameIdentifier Generation -->
+    <util:list id="shibboleth.SAML1NameIdentifierGenerators">
+
+        <ref bean="shibboleth.SAML1TransientGenerator" />
+
+        <!--
+        <bean parent="shibboleth.SAML1AttributeSourcedGenerator"
+            p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
+            p:attributeSourceIds="#{ {'mail'} }" />
+        -->
+                
+    </util:list>
+    
+</beans>
diff --git a/conf/services.properties b/conf/services.properties
new file mode 100644
index 0000000..eee86ee
--- /dev/null
+++ b/conf/services.properties
@@ -0,0 +1,65 @@
+# Configure the resources to load for various services,
+# and the settings for failure handling and auto-reload.
+
+# failFast=true prevents IdP startup if a configuration is bad
+# checkInterval = PT0S means never reload (this is the default)
+
+# Global default for fail-fast behavior of most subsystems
+# with individual override possible below.
+#idp.service.failFast = false
+
+#idp.service.logging.resource = %{idp.home}/conf/logback.xml
+#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
+
+#idp.service.metadata.resources = shibboleth.MetadataResolverResources
+#idp.service.metadata.failFast = false
+#idp.service.metadata.checkInterval = PT0S
+
+#idp.service.attribute.resolver.resources = shibboleth.AttributeResolverResources
+#idp.service.attribute.resolver.failFast = false
+idp.service.attribute.resolver.checkInterval = PT15M
+#idp.service.attribute.resolver.maskFailures = true
+
+#idp.service.attribute.filter.resources = shibboleth.AttributeFilterResources
+# NOTE: Failing the filter fast leaves no filters enabled.
+#idp.service.attribute.filter.failFast = false
+idp.service.attribute.filter.checkInterval = PT15M
+#idp.service.attribute.filter.maskFailures = true
+
+#idp.service.nameidGeneration.resources = shibboleth.NameIdentifierGenerationResources
+#idp.service.nameidGeneration.failFast = false
+idp.service.nameidGeneration.checkInterval = PT15M
+
+#idp.service.access.resources = shibboleth.AccessControlResources
+#idp.service.access.failFast = true
+idp.service.access.checkInterval = PT5M
+
+#idp.service.cas.registry.resources = shibboleth.CASServiceRegistryResources
+#idp.service.cas.registry.failFast = false
+idp.service.cas.registry.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.
+#idp.httpclient.useTrustEngineTLSSocketFactory = false
+#idp.httpclient.useSecurityEnhancedTLSSocketFactory = false
+#idp.httpclient.connectionDisregardTLSCertificate = false
+#idp.httpclient.connectionRequestTimeout = 60000
+#idp.httpclient.connectionTimeout = 60000
+#idp.httpclient.socketTimeout = 60000
+#idp.httpclient.maxConnectionsTotal = 100
+#idp.httpclient.maxConnectionsPerRoute = 100
+#idp.httpclient.memorycaching.maxCacheEntries = 50
+#idp.httpclient.memorycaching.maxCacheEntrySize = 1048576
+#idp.httpclient.filecaching.maxCacheEntries = 100
+#idp.httpclient.filecaching.maxCacheEntrySize = 10485760
+idp.httpclient.filecaching.cacheDirectory = %{idp.home}/tmp/httpClientCache
\ No newline at end of file
diff --git a/conf/services.xml b/conf/services.xml
new file mode 100644
index 0000000..313b636
--- /dev/null
+++ b/conf/services.xml
@@ -0,0 +1,144 @@
+<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">
+                           
+    <!-- Advanced configuration of services from SVN.
+       
+       To use an SVN resource you need to construct it and then inject it into 
+       The appropriate bean. To use property replacement you will need a separate 
+       resource pointing to the replacement phrase. 
+        
+       For example: 
+        
+    <bean id="AuthnMgr" class="org.tmatesoft.svn.core.auth.BasicAuthenticationManager">
+        <constructor-arg>
+            <null />
+        </constructor-arg>
+    </bean>
+    <bean id="ClientMgr" factory-method="newInstance"
+        class="org.tmatesoft.svn.core.wc.SVNClientManager"
+        p:authenticationManager-ref="AuthnMgr" />
+    <bean id="TheSVNURL" factory-method="create"
+        class="org.tmatesoft.svn.core.SVNURL">
+        <constructor-arg value="https" />
+        <constructor-arg>
+            <null />
+        </constructor-arg>
+        <constructor-arg value="svn.shibboleth.net" />
+        <constructor-arg value="-1" />
+        <constructor-arg
+            value="/utilities/spring-extensions/trunk/src/test/resources/data/" />
+        <constructor-arg value="false" />
+    </bean>
+    <bean id="TheSVNResource" class="net.shibboleth.ext.spring.resource.SVNResource">
+        <constructor-arg ref="ClientMgr" />
+        <constructor-arg ref="TheSVNURL" />
+        <constructor-arg value="D:/testdir/dir" />
+        <constructor-arg value="-1" />
+        <constructor-arg value="TestResource.txt" />
+    </bean>
+    
+    <util:list id="shibboleth.AttributeResolverResources">
+       <ref bean="TheSVNResource"/>
+       <value>path_to_properties_specifyingBean_file</value>
+    </util:list>
+    
+     see also https://wiki.shibboleth.net/confluence/display/IDP30/SVNResource
+              http://svnkit.com/javadoc/org/tmatesoft/svn/core/auth/BasicAuthenticationManager.html#constructor_detail 
+              http://svnkit.com/javadoc/org/tmatesoft/svn/core/SVNURL.html
+              
+    -->
+    
+    <!-- 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.
+    -->
+
+    <!-- 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>
+
+    <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>
+
+    <!--
+    This collection of resources differs slightly in that it should not include the file extension.
+    Message sources are internationalized, and Spring will search for a compatible language extension
+    and fall back to one with only a .properties extension.
+    -->
+    <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
new file mode 100644
index 0000000..f195014
--- /dev/null
+++ b/conf/session-manager.xml
@@ -0,0 +1,45 @@
+<?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>
+
+    <!-- Modify only to add extension types associated with non-built-in SSO protocols. -->
+    <bean id="shibboleth.SPSessionSerializerRegistry" parent="shibboleth.DefaultSPSessionSerializerRegistry">
+        <property name="mappings">
+            <map merge="true">
+            </map>
+        </property>
+    </bean>
+    
+    <!-- Modify only to add extension types associated with non-built-in SSO protocols. -->
+    <bean id="shibboleth.SessionTypeProtocolMap" parent="shibboleth.DefaultSessionTypeProtocolMap">
+        <property name="sourceMap">
+            <map merge="true">
+            </map>
+        </property>
+    </bean>
+        
+    <!--
+    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
new file mode 100644
index 0000000..752e5e0
--- /dev/null
+++ b/credentials/idp-backchannel.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDQzCCAiugAwIBAgIUbEZuLbKAcQzDND914sXQScSszvowDQYJKoZIhvcNAQEL
+BQAwITEfMB0GA1UEAwwWc2hpYmJvbGV0aC5leGFtcGxlLm9yZzAeFw0xNzA4MDMw
+MDA3NThaFw0zNzA4MDMwMDA3NThaMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhh
+bXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVr8AhZKq+
+QA/5F8EGRcf7uXfcVpN654RdICgpgB/zjvOpT0Qnw+YBraOpAJASUiTR/Ub5LUdC
+cya0qzMlScNrcimli+GAPUbyUkhzkP5YD8ikAfKy0X0acU7CMXkBahR6kYqc3mQO
+zGiDQImvDzfoDdOxP+cNyNhyPMgXQgdoIJzQFK9MKztXeq67aJ8lvx1R28JkIzzh
+kbGadvEe+Sp+5QE8NrLg4gjOtgFAGmugeZDFF70bZCAIIdh0rbWxCOk4lLjPtOkM
+4ZCEwhTG4WHvFS8Jhhv2qpQ+V+r6ifrFwetH6NeksY03jovMTGKnJt2Zr2nw/kM0
+YdXXgdClb2kRAgMBAAGjczBxMB0GA1UdDgQWBBQ5Yz+7JDneVDLb6W+47+mzrKGS
+RTBQBgNVHREESTBHghZzaGliYm9sZXRoLmV4YW1wbGUub3Jnhi1odHRwczovL3No
+aWJib2xldGguZXhhbXBsZS5vcmcvaWRwL3NoaWJib2xldGgwDQYJKoZIhvcNAQEL
+BQADggEBAFFyKRdpd/TLaF0iL9E2dnmOmWCXqqp53/z5PNTHFbeeriK6PB3w0Q06
+0ECHdjIbVfRYt15bZowyfUb9oIq+mw/tAsZs/B5nQagAgk4EzHfh63QaPZE6hgvJ
+t4I543cOlcPvDWhGuSXij9F6euOz2ke9lL1G5gTtgWvI5QvsKTDoPVXbXtw2fS0P
+iXZWsBA/0o+2KJxs3zz4y8wpFyl5s3ms5cG4W4A5xZQrUU2yZPwG49uSky/QhWR5
+b3F0TgvqbRFFTM3i1j//9bqs5RRGtY/M+pDaCxk2e8r9NXMWRb+DBe3xCdKDTIyw
+ZhTW1E3Hl11KDNf7E3lJwHUQpADwFCQ=
+-----END CERTIFICATE-----
diff --git a/credentials/idp-backchannel.p12 b/credentials/idp-backchannel.p12
new file mode 100644
index 0000000000000000000000000000000000000000..0ecbe3393cae3f3be7b6d8a4f3ce880da4c04666
GIT binary patch
literal 2596
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

literal 0
HcmV?d00001

diff --git a/credentials/idp-encryption.crt b/credentials/idp-encryption.crt
new file mode 100644
index 0000000..2b34b0c
--- /dev/null
+++ b/credentials/idp-encryption.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRDCCAiygAwIBAgIVAP3jGt1ixK5Z0RLcQxlvH4UgPKYXMA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAigTACHbG
+ERHyK2C9Bflj9eufn/gdvP+vZlduQZST8CHSVNrc0/39YR0yf725lFR8ThfOyMoP
+xwfQAhvRS5SZVXZQHhbABxJkjDCvf8DQN21UU+8UHdIYldY9uq2ub3La+YyHU5MS
+yXMSxj9pHec9tVlOe7oFjiGbBNcewBavSn+d+5YxzBZVR7k86bRwNtAfyPbZMwI0
+CZQ4NBjOQoqemDu/DuoZW7+Gefu5J+BprMJDDkBQ5NLPDWZwsvKpNpZnd45obxQq
+RTzndSI7eVJWb0nA8YUUaArK788W6Vz7NMLhLoq3VtOuW8PGWsKu9DimBHyxGA5C
+D8yAkiCXAUABCQIDAQABo3MwcTAdBgNVHQ4EFgQUNAeo+oRpwAej8Z963QfFGnEe
+wXQwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQBZxZeJXzgkTpfijeRs9QZL/Tnolml0ciqngOAjtGrK/QkhUuT0Yy1c
+Gg+wfQRlvpLW25SmwmIXVIY7YcFZWNH+rjgdyNO7gShzYk5Is2dSIJQHcZyL1ms3
+2I0RBL5pDyhl08+mVpeZ0APvW94K4cZ0iZ6X2pkBcfdVd3XRsFaJlo9iEOZfCE9N
++gT0WH7SU/OF1yKJJDLVPsfuyvgGJUuF+NFwqLX8BktCVThObleAjVSL/g/8cOVa
+FOZyH7qeX/+xmSbJgIx6f+HqHLkX2bwDvH77xGtYqvkVfLWKzt5LjAIjjqwzhUBC
+xFgugtW094wGu30sgexh+O/ZRgskcCFR
+-----END CERTIFICATE-----
diff --git a/credentials/idp-encryption.key b/credentials/idp-encryption.key
new file mode 100644
index 0000000..714aac8
--- /dev/null
+++ b/credentials/idp-encryption.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAigTACHbGERHyK2C9Bflj9eufn/gdvP+vZlduQZST8CHSVNrc
+0/39YR0yf725lFR8ThfOyMoPxwfQAhvRS5SZVXZQHhbABxJkjDCvf8DQN21UU+8U
+HdIYldY9uq2ub3La+YyHU5MSyXMSxj9pHec9tVlOe7oFjiGbBNcewBavSn+d+5Yx
+zBZVR7k86bRwNtAfyPbZMwI0CZQ4NBjOQoqemDu/DuoZW7+Gefu5J+BprMJDDkBQ
+5NLPDWZwsvKpNpZnd45obxQqRTzndSI7eVJWb0nA8YUUaArK788W6Vz7NMLhLoq3
+VtOuW8PGWsKu9DimBHyxGA5CD8yAkiCXAUABCQIDAQABAoIBABt8rrIA1Zl4tX4m
+Gf8il+HWN0gopeOKGGiNaQvuhzf/xF/Z5rjhkKDSq8f9BQShftAetbQPaez9hVOm
+Lpyaz57RnUsgxMWjyBqTZ6BNyin/wBenOZ5mxTayIEEZbfAMM8gXUKw4UjmEjWym
+HE00THnde1/wwEJ6NuFT5m/jFK4FR1vwnLyjZRPkZgcpfE6aO9bGJJ5mVt7MqH9f
+zivkFf5tmiuoXyaMk2rtzdykjWgf0RuQawPBbfdUOmnnbq6/qCFOIcbjPIqMyUwe
+HU3XrHeEgjnZG3xxYbcoY0rE5FsRpFGmPr9j1ZOIR0jLxy9SEancN5CYVaIc40Ye
+JwsCM/ECgYEA78KGsk6OgqW/vZgZr1mPVdmgijvYkdur1ChC8zQjn8l0SS7XfajF
+PYs/lf3wLCTcyPDv6QFH+Omr2XB2jfqPUCnRUEteUYyyUKz5CimW1CCTZ1GKlRuW
+uKcUsdnQ5SS+3b8njq2FtbDn5jUynOT/WrWkjrggLwmY4xeG2jYmOMMCgYEAk14D
+eyaZcQxUyCJOMPmuvEOPM1apzgN4/3c8IZf4Bb2vDJA70hcDgQmzGXc/hMFNP9WT
+b0KfH2bsD+HetpyjjZh2WHPzSdGK5+MVKJqPSxc5pncJsQJLyA4AkHaOOL2ZK03q
+QFKjoC6gqjoO2tgztFx1aM/PMpgAMxzllMIh4kMCgYEAhSWnPeBIXh+EEtsj8HAx
+HIEGGZ5Qj/fJPcG6JGuhGPx8WqPrwfn2x03MWxSxyyIRhnnfEavHd2D1MYS2IfSy
+n9cJSakBURJseEcG6nDcNSN+GJN8/X9bvWH0KSyISKiWYnjkk+Sja5o5vmtulxjJ
+Amv7XdK89MJEqGCJYCdQJJcCgYAfgVrnKjJlu8goXUUwLUERGLR1ulJlK9Ljct9V
+I0MwHwRcgD15xdfG74btq9PVkunr+sIhaDHSqdNP9e8CRWyl6fFrKabaokS7HI46
+dwipehamIw7cW+xNoci3GdGACfDEFE0/YSuAJFfO7MieOtia96VWOg9G9r4cL1JZ
+wkMyNwKBgGtcTxWUbbCLX9lJrGo50aJ/NAePmhEova72+egBKJq241ouUqZelvYV
+XVMF8WabICc80Gu3pYAf8kI2gVdyLAei8RbeLh5EKgZXdGn9/CDdAyXxL/P8Yd0H
+d3+dgTRO7HM6eX9ymxxme0ciqux43XdV6TyqAB4FzQ8tZbn3rVX8
+-----END RSA PRIVATE KEY-----
diff --git a/credentials/idp-signing.crt b/credentials/idp-signing.crt
new file mode 100644
index 0000000..93449c9
--- /dev/null
+++ b/credentials/idp-signing.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRDCCAiygAwIBAgIVAMeyqDjBqHXNh9j4nJ2Vzua8mfU7MA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlMzdKgBY
+YVP8F+y9HL4m8TeTAJt3C+R5ZVdFDnKXbN0ZlHneLwWfqf2VLnA6/00wlIueak75
+dnbrL7J/m28g20eYfAvwJ1Q+nwm2nTGM4veK1VwzhJK2NhIH3jvLG6DTik0CVNqG
+1eCWz47lHZktBbCKW7CdJRduUtBcjPL7scYWuzrUQHGejL1KmgEv939BBWtEh6fp
+xVFz8OjnJ7+NQA6+MYQ2l6ZpRDA+AGjQVRd4W7pGNkQlwVmDKHdqAD/iZZhHTrBU
+MTilE7k+NFZxueolWFs2rTbpP823tGp7mncEw72jblKZ2RQN9hbx+qz0bEmcZfGz
+OLsMbs4AJNpNrQIDAQABo3MwcTAdBgNVHQ4EFgQU/sxWnZsDNrrQVIWxe3a7sRYH
+7qAwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQCAG8qiJRZOSyc+et9l9bfDfhVslX2t5cVu+qORKyH7SgBiUnh698VT
+WwDTTLnh0MbPpp2ePRK9fwZlQAweNHkg1nLZcd4vG53O8juXHXEN4Y5ra1+lz/Ye
+LyO8tvTU9XlXXckFtlCCtF7S2LS/X8OH0bPXCHeJarq6ZNM8HSgjSaCbFqqNbKpv
+UgZEOKxVpEwOcasKlOalCyTKJylbtfqx+Lk92uZklmG7DzslE8cJIuqjS55m8qaj
+vmVhDFHYINiYbjfNOSeYwpxkhAHUw2flflqw/bCx7o+/XdU/ubHgN6q5ZHpnte24
+1w6+YrBjhjUAkYCfxOcTjlfE9IKXCrKS
+-----END CERTIFICATE-----
diff --git a/credentials/idp-signing.key b/credentials/idp-signing.key
new file mode 100644
index 0000000..d610df8
--- /dev/null
+++ b/credentials/idp-signing.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAlMzdKgBYYVP8F+y9HL4m8TeTAJt3C+R5ZVdFDnKXbN0ZlHne
+LwWfqf2VLnA6/00wlIueak75dnbrL7J/m28g20eYfAvwJ1Q+nwm2nTGM4veK1Vwz
+hJK2NhIH3jvLG6DTik0CVNqG1eCWz47lHZktBbCKW7CdJRduUtBcjPL7scYWuzrU
+QHGejL1KmgEv939BBWtEh6fpxVFz8OjnJ7+NQA6+MYQ2l6ZpRDA+AGjQVRd4W7pG
+NkQlwVmDKHdqAD/iZZhHTrBUMTilE7k+NFZxueolWFs2rTbpP823tGp7mncEw72j
+blKZ2RQN9hbx+qz0bEmcZfGzOLsMbs4AJNpNrQIDAQABAoIBACPVKbVBnAbkGKMS
+SYAwcmRIQ8gzp/lfLbSvzVtrUPfQTqaoqk6chhSDknc6Y5qzVe2PqbhkCEL05DH6
+RCyEGF914EyO+2gdK29VAXrdQdYuUmqK54UXZ3Wh5e8oawLeOdLmNJeGgE3k5axZ
+9uanymXCW6802sLh35llv8PZh68JaofS/nX54041u0d/Gl/EX/06P3gHorORN6PP
+dLLFeQYjpd6SQ+2rqsdT1uD9G8iEzrn7KsBXUa1KpWbcGkFb7KUZX0lZg+lyOIw/
+fU7HJle6L7aqrVYJ1VJE5ODrI6j4vkXKPGOTjQHQVdaYofbOSgxgIC+cmV5lXmc9
+1+6Fs6kCgYEA81dhUWQW31rPFk6oa/tEKxh3IOj6FolTJKAabze+Z1dUQjy1ZgMu
+u0cbvMbx0c5r71rFFD77Mr4gPKxE1lZTDNtI+L2Tsex0MxMroMizqKBw1NbFrl67
+fZHIYvqtPFdFVa/u3vfmLGlVUBgmqRW6dGX6EvpinkJpFvMoZfHUQhMCgYEAnIp2
+n45kASXo/UkBNObfLmz/nMD8GIse7UqoPlln5TGMxfP2Ui/Wwoprgsz6mVhuO2O+
+18j9MmT3X9ST4oGxsTiWixeJ4M0eeNb+jYT/hORj4R5vWR/Pv3GDUTFBX8SAXjkj
+5HQWtMls7bQtl1DYZyF+iUMfmF5h17D6QcnzKT8CgYADdPNR960HgT+93mIwHoKq
+Zg+TLRwYY90FgSy+9bjDuQ7eXgRprZPlXy46sUzQITGRVeXE0tw4rVDB6+SScul9
+HkRcHD1T4rsH2rbc8tzygUz5CRAH2Rqqvv5swYjieY7nl7c5/aWMbfajS6SI9GEQ
+tD4oNNxfySu7ArtJL3VHdwKBgGm4pdaqjuWrmcf91x/IULCFErjmKRvWUWPHCQta
+zG0g4scKNbBZ+LvYSjXDg/eunnvjqI8Jgd7YC62f3uSZ3M0ov5teoVK+lTbdVHt1
+eDBjIwV1zZOuhVrxKdPa5SDtkBiSlKgEsxUT+EotZqEMC6rTFydSuvLnw0KtlsZ5
+wox3AoGAcYuSljc2DpMiaiGQTaaTFejvWV0HfIwTafq4DRGx89vXCjfumMfBbyPh
+Lz6OvxoCfCgYDxmkMGp3ZGmPypXGzkM1YMJ6NPll9dlYEgWOkRpazPe6HtvkliK5
+RDJLO3TcpdDKkG4UOxDHiSA8Gj0sWqpt5CghGwWz5wn7Y/kwNAE=
+-----END RSA PRIVATE KEY-----
diff --git a/credentials/idp-userfacing.p12 b/credentials/idp-userfacing.p12
new file mode 100644
index 0000000000000000000000000000000000000000..1cb4efa59170f265d4e0fe8961dd247ec3449a4d
GIT binary patch
literal 2596
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

literal 0
HcmV?d00001

diff --git a/credentials/sealer.jks b/credentials/sealer.jks
new file mode 100644
index 0000000000000000000000000000000000000000..7daa3fd96f6a014b234f2f9ff55a9f1142948057
GIT binary patch
literal 500
zcmX?i?%X*B1_mY|W&~np2KM6A<f7CPLm)qPY4*&*HE$VMi;EbHlk;=+ic9nKl8Y(}
zO7iszit@`cQ&Nlcf>RT7Qd9hsvQm>v-13XOQ!4|C@=Ji6{Gzkrry`#l><$JRUQxs#
znUz?USOL?Itj*5McG=<WAq7kfEYS?Ssd>ryDXA#|iA9OI#U%_((N56}0zg5Ky{ReA
z`FSO&c_oDmbqq{C44egERgO97B@9A7APe+!67$magG-7s^U|$-K)y-L0ZN0^GglOp
z7J<xL^I7}{8%M|kkh=<ip5`~;W#QOa=+zcm?R1WbQKS^4niVK9;dl7tiq^~B+Och1
z*S{v`uiG-`wAq}yMP2=W-5xXCimGvNXgv64lYG#0(KRdhIpyE``Ta=Q!CN*VLDRsz
z_gj^@LFaCl@>dt1{gf7BR-5ZD@K1ZWNeI`hrNv8A8U)Nv6;3@ehrzRV!XJm2d%vB`
zr)_!1dh__>w$vMMtDhKayX3KQ*WUQ%^Y6~b4}Om=O)5H0lrV?|IJt&rmSp(4m^$XA
kgcM~K<fOW|2IG{l<Ep$UbhFjz=u6QI#o4ZADW$*K0k0arasU7T

literal 0
HcmV?d00001

diff --git a/credentials/sealer.kver b/credentials/sealer.kver
new file mode 100644
index 0000000..02a6b74
--- /dev/null
+++ b/credentials/sealer.kver
@@ -0,0 +1,2 @@
+#Thu Aug 03 00:07:58 UTC 2017
+CurrentVersion=1
diff --git a/edit-webapp/css/consent.css b/edit-webapp/css/consent.css
new file mode 100644
index 0000000..5daabee
--- /dev/null
+++ b/edit-webapp/css/consent.css
@@ -0,0 +1,150 @@
+.box {
+    width:600px;
+    margin-left: auto;
+    margin-right: auto;
+    margin-top: 50px;
+    background-color: white;
+   -webkit-box-shadow: 1px 1px 15px #999999;
+    -moz-box-shadow: 1px 1px 15px #999999;
+    box-shadow: 1px 1px 15px #999999;
+    -webkit-border-radius: 8px;
+    -moz-border-radius: 8px;
+    border-radius: 8px;
+    overflow: auto;
+    padding: 1.268em;
+}
+
+body {
+    font-family:Verdana, Geneva, sans-serif;
+    font-size: 12px;
+}
+
+h1 {
+    font-size: 13px;
+    padding-bottom: 12px;
+}
+
+a {
+    color: #00247D;
+    text-decoration: underline;
+}
+
+a:visited {
+    color: #00247D;
+    text-decoration: underline;
+}
+
+a:focus, a:hover, a:active {
+    color: #F39800;
+    text-decoration: underline;
+}
+
+#tou-content {
+    font-family:monospace;
+    width: 95%;
+    border: solid 1px #666;
+    margin: 4px;
+    padding: 10px;
+    overflow: hidden;
+}
+
+#tou-content li{
+    margin-bottom:10px;
+}
+
+#tou-acceptance {
+    width: 95%;
+    border: solid 1px #666;
+    background-color: #F0F0F0;
+    margin: 4px;
+    padding: 10px;
+    text-align: left;
+    overflow: hidden;
+}
+
+.service_name {
+    font-weight: bold;
+}
+
+.service_description {
+    font-style: italic;
+}
+
+.organization_name {
+}
+
+#attributeRelease-consent {
+    width: 95%;
+    border: solid 1px #666;
+    background-color: #F0F0F0;
+    margin: 4px;
+    overflow: hidden;
+}
+
+#attributeRelease {
+    width: 95%;
+    margin: 4px;
+    border: solid 1px black;
+    overflow: auto;
+}
+
+#attributeRelease table {
+    border-collapse: collapse;
+    border: none 0px white;
+    width: 100%;
+}
+
+#attributeRelease td {
+    padding: 3px 7px;
+    vertical-align: top;
+}
+
+#attributeRelease th  {
+    text-align: left;
+    font-size: 18px;
+    padding: 5px 7px;
+    background-color:#00247D;
+    color: white;
+}
+
+#attributeRelease tr:nth-of-type(even) {
+    background-color: #E4E5E3;
+}
+
+.federation_logo
+{
+	width: 50%;
+    float: left;
+    padding-top: 35px;
+    border: 0;
+}
+.organization_logo
+{
+	width: 50%;
+    float: right;
+    border: 0;
+}
+
+.form-error {
+  padding: 0;
+  color: #B61601;
+}
+
+/* Device specific styles */
+@media only screen and (max-device-width: 721px){
+  .box {
+      width: auto;
+      box-shadow: none;
+      border-radius: 0;
+      -webkit-box-shadow: none;
+      -webkit-border-radius: 0;
+      -moz-box-shadow: none;
+      -moz-border-radius: 0;
+      padding: 0;
+      margin-top:0;
+  }
+  #tou-content, #tou-acceptance{
+    /*width:87%;*/
+    width:auto;
+  }
+}
diff --git a/edit-webapp/css/logout.css b/edit-webapp/css/logout.css
new file mode 100644
index 0000000..26f1893
--- /dev/null
+++ b/edit-webapp/css/logout.css
@@ -0,0 +1,12 @@
+/* Success/Failure indicators for logout propagation. */
+
+.success {
+    background: url(../images/success-32x32.png) no-repeat left center;
+    line-height: 36px;
+    padding-left: 36px;
+}
+.failure {
+    background: url(../images/failure-32x32.png) no-repeat left center;
+    line-height: 36px;
+    padding-left: 36px;
+}
diff --git a/edit-webapp/css/main.css b/edit-webapp/css/main.css
new file mode 100644
index 0000000..116b31e
--- /dev/null
+++ b/edit-webapp/css/main.css
@@ -0,0 +1,165 @@
+* {
+    margin: 0;
+    padding: 0;
+}
+header, footer, section, nav {
+    display: block;
+}
+html, body {
+    height: 100%;
+}
+body {
+    font-family:Verdana, Geneva, sans-serif;
+    font-size: 12px;
+    line-height: 1.5;
+    color: #717171;
+    background: #717171;
+}
+a:link,
+a:visited {
+    text-decoration: none;
+    color: #717171;
+}
+img {
+    max-width: 100%;
+    margin-bottom: 12px;
+}
+
+.wrapper {
+    background: #ffffff;
+}
+
+.container {
+    position: relative;
+    left: 34%;
+    width: 540px;
+    margin-left: -270px;
+}
+.container-footer {
+    padding-top: 12px;
+}
+@media only screen and (max-width: 1020px) {
+    .container {
+        left: 45%;
+    }
+}
+@media only screen and (max-width: 650px) {
+    .container {
+        position: static;
+        margin: 0 auto;
+        width: 280px;
+    }
+}
+
+header {
+    padding: 20px 0;
+}
+
+.logo img {
+    border: none;
+}
+@media only screen and (max-width: 650px) {
+    .logo img {
+        display: none;
+    }
+    .logo {
+        background: url(../images/dummylogo-mobile.png) no-repeat top center;
+        display: block;
+        height: 115px;
+        width: 100px;
+        margin: 0 auto;
+    }
+}
+
+.content {
+    padding-bottom: 80px;
+    overflow: hidden;
+}
+
+.column {
+    float: left;
+}
+.column.one {
+    width: 50%;
+    margin-right: 48px;
+}
+
+form {
+    width: 240px;
+    padding-bottom: 21px;
+}
+form label { /* labels are hidden */
+    font-weight: bold;
+}
+form legend {
+    font-size:1.2em;
+    margin-bottom: 12px;
+}
+.form-element-wrapper {
+    margin-bottom: 12px;
+}
+.form-element {
+    width: 100%;
+    padding: 13px 12px;
+    border: none;
+    font-size: 14px;
+    border-radius: 4px;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+}
+.form-field {
+    color: #B7B7B7;
+    border: 1px solid #B7B7B7;
+}
+.form-field-focus,
+.form-field:focus,
+input[type="text"]:focus {
+    color: #333333;
+    border-color: #333;
+}
+.form-button {
+    background: #B61601;
+    box-sizing: content-box;
+    -moz-box-sizing: content-box;
+    color: #ffffff;
+    cursor: pointer;
+}
+.form-button:hover {
+    background: #FF6400;
+}
+.form-error {
+    padding: 0;
+    color: #B61601;
+}
+
+.list-help {
+    margin-top: 40px; /* offset padding on first anchor */
+    list-style: none;
+}
+.list-help-item a {
+    display: block;
+    padding: 6px 0;
+}
+.item-marker {
+    color: #be0000;
+}
+
+footer {
+    color: #ffffff;
+    font-size: 11px;
+    background: #717171;
+}
+.footer-text {
+    margin-bottom: 12px;
+}
+.footer-links a:link,
+.footer-links a:visited {
+    color: #ffffff;
+    font-weight: bold;
+}
+.footer-links a:after {
+    content: "\00a0\00a0\00a0|\00a0\00a0";
+}
+.footer-links a.last:after {
+    content: "";
+}
diff --git a/edit-webapp/images/dummylogo-mobile.png b/edit-webapp/images/dummylogo-mobile.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ba3c95a12a93606734df54750d674bee02eaa96
GIT binary patch
literal 8208
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
C`x=k{

literal 0
HcmV?d00001

diff --git a/edit-webapp/images/dummylogo.png b/edit-webapp/images/dummylogo.png
new file mode 100644
index 0000000000000000000000000000000000000000..e89ede6e2089b0e21db8f5374d6ab9f5caa2fbc3
GIT binary patch
literal 13742
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

literal 0
HcmV?d00001

diff --git a/edit-webapp/images/failure-32x32.png b/edit-webapp/images/failure-32x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c48e4669dccf145e5a6cd26488311d0a59c963e
GIT binary patch
literal 2580
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

literal 0
HcmV?d00001

diff --git a/edit-webapp/images/success-32x32.png b/edit-webapp/images/success-32x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa512048d8fe96fc4b37db81fc5354a80b191bdd
GIT binary patch
literal 2448
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

literal 0
HcmV?d00001

diff --git a/messages/messages.properties b/messages/messages.properties
new file mode 100644
index 0000000..5f94396
--- /dev/null
+++ b/messages/messages.properties
@@ -0,0 +1,2 @@
+# You can define message properties here to override messages defined in
+# system/messages/ or to add your own messages.
diff --git a/metadata/idp-metadata.xml b/metadata/idp-metadata.xml
new file mode 100644
index 0000000..e11e5b7
--- /dev/null
+++ b/metadata/idp-metadata.xml
@@ -0,0 +1,219 @@
+<?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" entityID="https://shibboleth.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 shibboleth.example.org</mdui:DisplayName>
+                <mdui:Description xml:lang="en">Enter a description of your IdP at shibboleth.example.org</mdui:Description>
+                <mdui:Logo height="80" width="80">https://shibboleth.example.org/Path/To/Logo.png</mdui:Logo>
+            </mdui:UIInfo>
+-->
+        </Extensions>
+
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDQzCCAiugAwIBAgIUbEZuLbKAcQzDND914sXQScSszvowDQYJKoZIhvcNAQEL
+BQAwITEfMB0GA1UEAwwWc2hpYmJvbGV0aC5leGFtcGxlLm9yZzAeFw0xNzA4MDMw
+MDA3NThaFw0zNzA4MDMwMDA3NThaMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhh
+bXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVr8AhZKq+
+QA/5F8EGRcf7uXfcVpN654RdICgpgB/zjvOpT0Qnw+YBraOpAJASUiTR/Ub5LUdC
+cya0qzMlScNrcimli+GAPUbyUkhzkP5YD8ikAfKy0X0acU7CMXkBahR6kYqc3mQO
+zGiDQImvDzfoDdOxP+cNyNhyPMgXQgdoIJzQFK9MKztXeq67aJ8lvx1R28JkIzzh
+kbGadvEe+Sp+5QE8NrLg4gjOtgFAGmugeZDFF70bZCAIIdh0rbWxCOk4lLjPtOkM
+4ZCEwhTG4WHvFS8Jhhv2qpQ+V+r6ifrFwetH6NeksY03jovMTGKnJt2Zr2nw/kM0
+YdXXgdClb2kRAgMBAAGjczBxMB0GA1UdDgQWBBQ5Yz+7JDneVDLb6W+47+mzrKGS
+RTBQBgNVHREESTBHghZzaGliYm9sZXRoLmV4YW1wbGUub3Jnhi1odHRwczovL3No
+aWJib2xldGguZXhhbXBsZS5vcmcvaWRwL3NoaWJib2xldGgwDQYJKoZIhvcNAQEL
+BQADggEBAFFyKRdpd/TLaF0iL9E2dnmOmWCXqqp53/z5PNTHFbeeriK6PB3w0Q06
+0ECHdjIbVfRYt15bZowyfUb9oIq+mw/tAsZs/B5nQagAgk4EzHfh63QaPZE6hgvJ
+t4I543cOlcPvDWhGuSXij9F6euOz2ke9lL1G5gTtgWvI5QvsKTDoPVXbXtw2fS0P
+iXZWsBA/0o+2KJxs3zz4y8wpFyl5s3ms5cG4W4A5xZQrUU2yZPwG49uSky/QhWR5
+b3F0TgvqbRFFTM3i1j//9bqs5RRGtY/M+pDaCxk2e8r9NXMWRb+DBe3xCdKDTIyw
+ZhTW1E3Hl11KDNf7E3lJwHUQpADwFCQ=
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDRDCCAiygAwIBAgIVAMeyqDjBqHXNh9j4nJ2Vzua8mfU7MA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlMzdKgBY
+YVP8F+y9HL4m8TeTAJt3C+R5ZVdFDnKXbN0ZlHneLwWfqf2VLnA6/00wlIueak75
+dnbrL7J/m28g20eYfAvwJ1Q+nwm2nTGM4veK1VwzhJK2NhIH3jvLG6DTik0CVNqG
+1eCWz47lHZktBbCKW7CdJRduUtBcjPL7scYWuzrUQHGejL1KmgEv939BBWtEh6fp
+xVFz8OjnJ7+NQA6+MYQ2l6ZpRDA+AGjQVRd4W7pGNkQlwVmDKHdqAD/iZZhHTrBU
+MTilE7k+NFZxueolWFs2rTbpP823tGp7mncEw72jblKZ2RQN9hbx+qz0bEmcZfGz
+OLsMbs4AJNpNrQIDAQABo3MwcTAdBgNVHQ4EFgQU/sxWnZsDNrrQVIWxe3a7sRYH
+7qAwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQCAG8qiJRZOSyc+et9l9bfDfhVslX2t5cVu+qORKyH7SgBiUnh698VT
+WwDTTLnh0MbPpp2ePRK9fwZlQAweNHkg1nLZcd4vG53O8juXHXEN4Y5ra1+lz/Ye
+LyO8tvTU9XlXXckFtlCCtF7S2LS/X8OH0bPXCHeJarq6ZNM8HSgjSaCbFqqNbKpv
+UgZEOKxVpEwOcasKlOalCyTKJylbtfqx+Lk92uZklmG7DzslE8cJIuqjS55m8qaj
+vmVhDFHYINiYbjfNOSeYwpxkhAHUw2flflqw/bCx7o+/XdU/ubHgN6q5ZHpnte24
+1w6+YrBjhjUAkYCfxOcTjlfE9IKXCrKS
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+        <KeyDescriptor use="encryption">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDRDCCAiygAwIBAgIVAP3jGt1ixK5Z0RLcQxlvH4UgPKYXMA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAigTACHbG
+ERHyK2C9Bflj9eufn/gdvP+vZlduQZST8CHSVNrc0/39YR0yf725lFR8ThfOyMoP
+xwfQAhvRS5SZVXZQHhbABxJkjDCvf8DQN21UU+8UHdIYldY9uq2ub3La+YyHU5MS
+yXMSxj9pHec9tVlOe7oFjiGbBNcewBavSn+d+5YxzBZVR7k86bRwNtAfyPbZMwI0
+CZQ4NBjOQoqemDu/DuoZW7+Gefu5J+BprMJDDkBQ5NLPDWZwsvKpNpZnd45obxQq
+RTzndSI7eVJWb0nA8YUUaArK788W6Vz7NMLhLoq3VtOuW8PGWsKu9DimBHyxGA5C
+D8yAkiCXAUABCQIDAQABo3MwcTAdBgNVHQ4EFgQUNAeo+oRpwAej8Z963QfFGnEe
+wXQwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQBZxZeJXzgkTpfijeRs9QZL/Tnolml0ciqngOAjtGrK/QkhUuT0Yy1c
+Gg+wfQRlvpLW25SmwmIXVIY7YcFZWNH+rjgdyNO7gShzYk5Is2dSIJQHcZyL1ms3
+2I0RBL5pDyhl08+mVpeZ0APvW94K4cZ0iZ6X2pkBcfdVd3XRsFaJlo9iEOZfCE9N
++gT0WH7SU/OF1yKJJDLVPsfuyvgGJUuF+NFwqLX8BktCVThObleAjVSL/g/8cOVa
+FOZyH7qeX/+xmSbJgIx6f+HqHLkX2bwDvH77xGtYqvkVfLWKzt5LjAIjjqwzhUBC
+xFgugtW094wGu30sgexh+O/ZRgskcCFR
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+
+        <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://shibboleth.example.org:8443/idp/profile/SAML1/SOAP/ArtifactResolution" index="1"/>
+        <ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://shibboleth.example.org:8443/idp/profile/SAML2/SOAP/ArtifactResolution" index="2"/>
+
+        <!--
+        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://shibboleth.example.org/idp/profile/SAML2/Redirect/SLO"/>
+        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://shibboleth.example.org/idp/profile/SAML2/POST/SLO"/>
+        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://shibboleth.example.org/idp/profile/SAML2/POST-SimpleSign/SLO"/>
+        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://shibboleth.example.org:8443/idp/profile/SAML2/SOAP/SLO"/>
+        -->
+
+        <SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest" Location="https://shibboleth.example.org/idp/profile/Shibboleth/SSO"/>
+        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://shibboleth.example.org/idp/profile/SAML2/POST/SSO"/>
+        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://shibboleth.example.org/idp/profile/SAML2/POST-SimpleSign/SSO"/>
+        <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://shibboleth.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>
+
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDQzCCAiugAwIBAgIUbEZuLbKAcQzDND914sXQScSszvowDQYJKoZIhvcNAQEL
+BQAwITEfMB0GA1UEAwwWc2hpYmJvbGV0aC5leGFtcGxlLm9yZzAeFw0xNzA4MDMw
+MDA3NThaFw0zNzA4MDMwMDA3NThaMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhh
+bXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVr8AhZKq+
+QA/5F8EGRcf7uXfcVpN654RdICgpgB/zjvOpT0Qnw+YBraOpAJASUiTR/Ub5LUdC
+cya0qzMlScNrcimli+GAPUbyUkhzkP5YD8ikAfKy0X0acU7CMXkBahR6kYqc3mQO
+zGiDQImvDzfoDdOxP+cNyNhyPMgXQgdoIJzQFK9MKztXeq67aJ8lvx1R28JkIzzh
+kbGadvEe+Sp+5QE8NrLg4gjOtgFAGmugeZDFF70bZCAIIdh0rbWxCOk4lLjPtOkM
+4ZCEwhTG4WHvFS8Jhhv2qpQ+V+r6ifrFwetH6NeksY03jovMTGKnJt2Zr2nw/kM0
+YdXXgdClb2kRAgMBAAGjczBxMB0GA1UdDgQWBBQ5Yz+7JDneVDLb6W+47+mzrKGS
+RTBQBgNVHREESTBHghZzaGliYm9sZXRoLmV4YW1wbGUub3Jnhi1odHRwczovL3No
+aWJib2xldGguZXhhbXBsZS5vcmcvaWRwL3NoaWJib2xldGgwDQYJKoZIhvcNAQEL
+BQADggEBAFFyKRdpd/TLaF0iL9E2dnmOmWCXqqp53/z5PNTHFbeeriK6PB3w0Q06
+0ECHdjIbVfRYt15bZowyfUb9oIq+mw/tAsZs/B5nQagAgk4EzHfh63QaPZE6hgvJ
+t4I543cOlcPvDWhGuSXij9F6euOz2ke9lL1G5gTtgWvI5QvsKTDoPVXbXtw2fS0P
+iXZWsBA/0o+2KJxs3zz4y8wpFyl5s3ms5cG4W4A5xZQrUU2yZPwG49uSky/QhWR5
+b3F0TgvqbRFFTM3i1j//9bqs5RRGtY/M+pDaCxk2e8r9NXMWRb+DBe3xCdKDTIyw
+ZhTW1E3Hl11KDNf7E3lJwHUQpADwFCQ=
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+        <KeyDescriptor use="signing">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDRDCCAiygAwIBAgIVAMeyqDjBqHXNh9j4nJ2Vzua8mfU7MA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlMzdKgBY
+YVP8F+y9HL4m8TeTAJt3C+R5ZVdFDnKXbN0ZlHneLwWfqf2VLnA6/00wlIueak75
+dnbrL7J/m28g20eYfAvwJ1Q+nwm2nTGM4veK1VwzhJK2NhIH3jvLG6DTik0CVNqG
+1eCWz47lHZktBbCKW7CdJRduUtBcjPL7scYWuzrUQHGejL1KmgEv939BBWtEh6fp
+xVFz8OjnJ7+NQA6+MYQ2l6ZpRDA+AGjQVRd4W7pGNkQlwVmDKHdqAD/iZZhHTrBU
+MTilE7k+NFZxueolWFs2rTbpP823tGp7mncEw72jblKZ2RQN9hbx+qz0bEmcZfGz
+OLsMbs4AJNpNrQIDAQABo3MwcTAdBgNVHQ4EFgQU/sxWnZsDNrrQVIWxe3a7sRYH
+7qAwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQCAG8qiJRZOSyc+et9l9bfDfhVslX2t5cVu+qORKyH7SgBiUnh698VT
+WwDTTLnh0MbPpp2ePRK9fwZlQAweNHkg1nLZcd4vG53O8juXHXEN4Y5ra1+lz/Ye
+LyO8tvTU9XlXXckFtlCCtF7S2LS/X8OH0bPXCHeJarq6ZNM8HSgjSaCbFqqNbKpv
+UgZEOKxVpEwOcasKlOalCyTKJylbtfqx+Lk92uZklmG7DzslE8cJIuqjS55m8qaj
+vmVhDFHYINiYbjfNOSeYwpxkhAHUw2flflqw/bCx7o+/XdU/ubHgN6q5ZHpnte24
+1w6+YrBjhjUAkYCfxOcTjlfE9IKXCrKS
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+        <KeyDescriptor use="encryption">
+            <ds:KeyInfo>
+                    <ds:X509Data>
+                        <ds:X509Certificate>
+MIIDRDCCAiygAwIBAgIVAP3jGt1ixK5Z0RLcQxlvH4UgPKYXMA0GCSqGSIb3DQEB
+CwUAMCExHzAdBgNVBAMMFnNoaWJib2xldGguZXhhbXBsZS5vcmcwHhcNMTcwODAz
+MDAwNzU3WhcNMzcwODAzMDAwNzU3WjAhMR8wHQYDVQQDDBZzaGliYm9sZXRoLmV4
+YW1wbGUub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAigTACHbG
+ERHyK2C9Bflj9eufn/gdvP+vZlduQZST8CHSVNrc0/39YR0yf725lFR8ThfOyMoP
+xwfQAhvRS5SZVXZQHhbABxJkjDCvf8DQN21UU+8UHdIYldY9uq2ub3La+YyHU5MS
+yXMSxj9pHec9tVlOe7oFjiGbBNcewBavSn+d+5YxzBZVR7k86bRwNtAfyPbZMwI0
+CZQ4NBjOQoqemDu/DuoZW7+Gefu5J+BprMJDDkBQ5NLPDWZwsvKpNpZnd45obxQq
+RTzndSI7eVJWb0nA8YUUaArK788W6Vz7NMLhLoq3VtOuW8PGWsKu9DimBHyxGA5C
+D8yAkiCXAUABCQIDAQABo3MwcTAdBgNVHQ4EFgQUNAeo+oRpwAej8Z963QfFGnEe
+wXQwUAYDVR0RBEkwR4IWc2hpYmJvbGV0aC5leGFtcGxlLm9yZ4YtaHR0cHM6Ly9z
+aGliYm9sZXRoLmV4YW1wbGUub3JnL2lkcC9zaGliYm9sZXRoMA0GCSqGSIb3DQEB
+CwUAA4IBAQBZxZeJXzgkTpfijeRs9QZL/Tnolml0ciqngOAjtGrK/QkhUuT0Yy1c
+Gg+wfQRlvpLW25SmwmIXVIY7YcFZWNH+rjgdyNO7gShzYk5Is2dSIJQHcZyL1ms3
+2I0RBL5pDyhl08+mVpeZ0APvW94K4cZ0iZ6X2pkBcfdVd3XRsFaJlo9iEOZfCE9N
++gT0WH7SU/OF1yKJJDLVPsfuyvgGJUuF+NFwqLX8BktCVThObleAjVSL/g/8cOVa
+FOZyH7qeX/+xmSbJgIx6f+HqHLkX2bwDvH77xGtYqvkVfLWKzt5LjAIjjqwzhUBC
+xFgugtW094wGu30sgexh+O/ZRgskcCFR
+                        </ds:X509Certificate>
+                    </ds:X509Data>
+            </ds:KeyInfo>
+
+        </KeyDescriptor>
+
+        <AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://shibboleth.example.org:8443/idp/profile/SAML1/SOAP/AttributeQuery"/>
+        <!-- <AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://shibboleth.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/client-storage/client-storage-read.vm b/views/client-storage/client-storage-read.vm
new file mode 100644
index 0000000..1993c14
--- /dev/null
+++ b/views/client-storage/client-storage-read.vm
@@ -0,0 +1,53 @@
+##
+## Velocity template to read from local storage.
+##
+## 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
+## loadContext - context with details about the storage keys to load
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-read.suffix", "Loading Session Information"))
+##
+<!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">
+        <script>
+        <!--
+        #include( "client-storage/local-storage-read.js" )
+        // -->
+        </script>
+    </head>
+    <body onload="doLoad()">
+        <div class="wrapper">
+            <div class="container">
+                <header>
+                    <h3>$title - $titleSuffix</h3>
+                </header>
+                <div class="content">
+                $springMacroRequestContext.getMessage("idp.client-storage-read.text", "Loading login session information from the browser...")
+                </div>
+                <noscript>
+                    <div class="content">
+                    $springMacroRequestContext.getMessage("idp.client-storage.no-js", "Since your browser does not support JavaScript, you must press the Continue button once to proceed.")
+                    </div>
+                </noscript>
+                #parse( "client-storage/read.vm" )
+            </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/client-storage/client-storage-write.vm b/views/client-storage/client-storage-write.vm
new file mode 100644
index 0000000..4b92d6b
--- /dev/null
+++ b/views/client-storage/client-storage-write.vm
@@ -0,0 +1,53 @@
+##
+## Velocity template to write to local storage.
+##
+## 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
+## saveContext - context with details about the storage data to save
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($titleSuffix = $springMacroRequestContext.getMessage("idp.client-storage-write.suffix", "Saving Session Information..."))
+##
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+    <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">
+        <script>
+        <!--
+        #include( "client-storage/local-storage-write.js" )
+        // -->
+        </script>
+    </head>
+    <body onload="doSave()">
+        <div class="wrapper">
+            <div class="container">
+                <header>
+                    <h3>$title - $titleSuffix</h3>
+                </header>
+                <div class="content">
+                $springMacroRequestContext.getMessage("idp.client-storage-write.text", "Saving login session information to the browser...")
+                </div>
+                <noscript>
+                    <div class="content">
+                    $springMacroRequestContext.getMessage("idp.client-storage.no-js", "Since your browser does not support JavaScript, you must press the Continue button once to proceed.")
+                    </div>
+                </noscript>
+                #parse( "client-storage/write.vm" )
+            </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
new file mode 100644
index 0000000..cf4f96a
--- /dev/null
+++ b/views/duo.vm
@@ -0,0 +1,83 @@
+##
+## 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
new file mode 100644
index 0000000..dcb8e2b
--- /dev/null
+++ b/views/error.vm
@@ -0,0 +1,73 @@
+##
+## Velocity Template for error end-state
+##
+## Velocity context will contain the following properties
+## flowRequestContext - the Spring Web Flow RequestContext
+## profileRequestContext - root of context tree
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+#set ($title = $springMacroRequestContext.getMessage("idp.title", "Web Login Service"))
+#set ($defaultTitleSuffix = $springMacroRequestContext.getMessage("idp.title.suffix", "Error"))
+##
+#if ($flowRequestContext)
+	## This handles flow events, the most common case.
+    #set ($eventId = $flowRequestContext.getCurrentEvent().getId())
+    #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error"))
+    #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix"))
+    #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId"))
+    #if ($eventId == "AccessDenied" or $eventId == "ContextCheckDenied")
+        $response.setStatus(403)
+    #elseif ($eventId == "AttributeReleaseRejected" || $eventId == "TermsRejected")
+        $response.setStatus(200)
+    #elseif ($eventKey == "unexpected" || $eventKey == "runtime-error" || $eventKey == "error")
+        $response.setStatus(500)
+    #else
+        $response.setStatus(400)
+    #end
+#elseif ($exception)
+	## This handles exceptions that reach the Spring-MVC exception handler.
+    #set ($eventId = $exception.getClass().getSimpleName())
+    #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "error"))
+    #set ($titleSuffix = $springMacroRequestContext.getMessage("${eventKey}.title", "$defaultTitleSuffix"))
+    #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "$defaultTitleSuffix: $eventId"))
+#else
+	## This is a catch-all that theoretically shouldn't happen?
+    #set ($titleSuffix = $defaultTitleSuffix)
+    #set ($message = $springMacroRequestContext.getMessage("idp.message", "An unidentified error occurred."))
+#end
+##
+<!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">
+            #evaluate($message)
+            </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/attribute-release.vm b/views/intercept/attribute-release.vm
new file mode 100644
index 0000000..0b74551
--- /dev/null
+++ b/views/intercept/attribute-release.vm
@@ -0,0 +1,158 @@
+##
+## 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
+## 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
new file mode 100644
index 0000000..4395844
--- /dev/null
+++ b/views/intercept/expiring-password.vm
@@ -0,0 +1,54 @@
+##
+## 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/terms-of-use.vm b/views/intercept/terms-of-use.vm
new file mode 100644
index 0000000..1bf12c7
--- /dev/null
+++ b/views/intercept/terms-of-use.vm
@@ -0,0 +1,67 @@
+##
+## 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
new file mode 100644
index 0000000..44676b3
--- /dev/null
+++ b/views/login-error.vm
@@ -0,0 +1,24 @@
+## Velocity Template for login error message production, included by login.vm
+##
+## authenticationErrorContext - context containing error data, if available
+##
+#if ($authenticationErrorContext && $authenticationErrorContext.getClassifiedErrors().size() > 0 && $authenticationErrorContext.getClassifiedErrors().iterator().next() != "ReselectFlow")
+    ## 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"))
+#elseif ($authenticationErrorContext && $authenticationErrorContext.getExceptions().size() > 0)
+    ## This handles login exceptions that are left unclassified.
+    #set ($loginException = $authenticationErrorContext.getExceptions().get(0))
+    #if ($loginException.getMessage())
+        #set ($message = "Login Failure: $loginException.getMessage()")
+    #else
+    	#set ($message = $loginException.toString())
+    #end
+#end
+
+#if ($message)
+    <section>
+        <p class="form-element form-error">$encoder.encodeForHTML($message)</p>
+    </section>
+#end
diff --git a/views/login.vm b/views/login.vm
new file mode 100644
index 0000000..c421a99
--- /dev/null
+++ b/views/login.vm
@@ -0,0 +1,140 @@
+##
+## Velocity Template for DisplayUsernamePasswordPage 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
+## authenticationErrorContext - context with login error state
+## authenticationWarningContext - context with login warning state
+## ldapResponseContext - context with LDAP state (if using native LDAP)
+## rpUIContext - the context with SP UI information from the metadata
+## extendedAuthenticationFlows - collection of "extended" AuthenticationFlowDescriptor objects
+## passwordPrincipals - contents of the shibboleth.authn.Password.PrincipalOverride bean
+## 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'))
+#set ($username = $authenticationContext.getSubcontext('net.shibboleth.idp.authn.context.UsernamePasswordContext', true).getUsername())
+#set ($passwordEnabled = false)
+#if (!$passwordPrincipals or $passwordPrincipals.isEmpty() or $authenticationContext.isAcceptable($passwordPrincipals))
+  #set ($passwordEnabled = true)
+#end
+##
+<!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")">
+        </header>
+
+        <div class="content">
+          <div class="column one">
+            #parse("login-error.vm")
+
+            <form action="$flowExecutionUrl" method="post">
+
+            #set ($serviceName = $rpUIContext.serviceName)
+            #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
+              <legend>
+                #springMessageText("idp.login.loginTo", "Login to") $encoder.encodeForHTML($serviceName)
+              </legend>
+            #end
+                        
+            #if ($passwordEnabled)
+              <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">
+              </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="">
+              </div>
+
+              <div class="form-element-wrapper">
+                <input type="checkbox" name="donotcache" value="1" id="donotcache">
+                <label for="donotcache">#springMessageText("idp.login.donotcache", "Don't Remember Login")</label>
+               </div>
+            #end
+
+              <div class="form-element-wrapper">
+                <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>
+
+            #if ($passwordEnabled)
+              <div class="form-element-wrapper">
+                <button class="form-element form-button" type="submit" name="_eventId_proceed"
+                    onClick="this.childNodes[0].nodeValue='#springMessageText("idp.login.pleasewait", "Logging in, please wait...")'"
+                    >#springMessageText("idp.login.login", "Login")</button>
+              </div>
+            #end
+
+            #foreach ($extFlow in $extendedAuthenticationFlows)
+              #if ($authenticationContext.isAcceptable($extFlow) and $extFlow.apply(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/',''))
+                  </button>
+                </div>
+              #end
+            #end
+            </form>
+
+			#*
+              //
+              //    SP Description & Logo (optional)
+              //    These idpui lines will display added information (if available
+              //    in the metadata) about the Service Provider (SP) that requested
+              //    authentication. These idpui lines are "active" in this example
+              //    (not commented out) - this extra SP info will be displayed.
+              //    Remove or comment out these lines to stop the display of the
+              //    added SP information.
+              //
+            *#
+            #set ($logo = $rpUIContext.getLogo())
+            #if ($logo)
+              <img src= "$encoder.encodeForHTMLAttribute($logo)"
+                  alt="$encoder.encodeForHTMLAttribute($serviceName)">
+            #end
+            #set ($desc = $rpUIContext.getServiceDescription())
+            #if ($desc)
+              $encoder.encodeForHTML($desc)
+            #end
+            
+          </div>
+          <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>
+              #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>
+            </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>
\ No newline at end of file
diff --git a/views/logout-complete.vm b/views/logout-complete.vm
new file mode 100644
index 0000000..d780252
--- /dev/null
+++ b/views/logout-complete.vm
@@ -0,0 +1,59 @@
+##
+## Velocity Template for logout flow's concluding view-state (no propagation)
+##
+## 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
+## logoutContext - context with SPSession details for logout operation
+## multiRPContext - context with RelyingPartyContexts and possibly 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
+##
+<!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")">
+        </header>
+
+        <div class="content">
+          <div class="column one">
+            <p>#springMessageText("idp.logout.local", "You elected not to log out of all the applications accessed during your session.")</p>
+          </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>
+            </ul>
+          </div>
+        </div>
+      </div>
+
+      <!-- If SAML logout, complete the flow by adding a hidden iframe. -->
+      #if ( $profileRequestContext.getProfileId().contains("saml2/logout") )
+          <iframe style="display:none" src="$flowExecutionUrl&_eventId=proceed"></iframe>
+      #end
+
+      <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/logout-propagate.vm b/views/logout-propagate.vm
new file mode 100644
index 0000000..86b3fa1
--- /dev/null
+++ b/views/logout-propagate.vm
@@ -0,0 +1,58 @@
+##
+## Velocity Template for logout flow's concluding view-state (with propagation)
+##
+## 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
+## logoutContext - context with SPSession details for logout operation
+## multiRPContext - context with RelyingPartyContexts and possibly SP UI information from the metadata
+## htmlEncoder - HTMLEncoder class
+## urlEncoder - urlEncoder class
+## codecUtil - CodecUtil 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">
+        <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/logout.css">
+    </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">
+              <p>#springMessageText("idp.logout.attempt", "Attempting to log out of the following services:")</p>
+              #parse("logout/propagate.vm")
+          </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>
+            </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>
\ No newline at end of file
diff --git a/views/logout.vm b/views/logout.vm
new file mode 100644
index 0000000..2342855
--- /dev/null
+++ b/views/logout.vm
@@ -0,0 +1,91 @@
+##
+## Velocity Template for logout flow's starting 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
+## logoutContext - context with SPSession details for logout operation
+## multiRPContext - context with RelyingPartyContexts and possibly 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
+##
+<!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() )
+            <meta http-equiv="refresh" content="10;url=$flowExecutionUrl&_eventId=propagate">
+        #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="container">
+        <header>
+          <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
+        </header>
+
+        <div class="content">
+          <div class="column one">
+            <p>This page is displayed when a logout operation at the Identity Provider completes. This page is an example
+            and should be customized. It is not fully internationalized because the presentation will be a highly localized
+            decision, and we don't have a good suggestion for a 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>
+
+                <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())
+                    #set ($rpCtx = $multiRPContext.getRelyingPartyContextById($sp))
+                    #if ($rpCtx)
+                      #set ($rpUIContext = $rpCtx.getSubcontext("net.shibboleth.idp.ui.context.RelyingPartyUIContext"))
+                    #end
+                    #if ($rpUIContext and $rpUIContext.getServiceName())
+                      <li>$encoder.encodeForHTML($rpUIContext.getServiceName())</li>
+                    #else
+                      <li>$encoder.encodeForHTML($sp)</li>
+                    #end
+                #end
+                </ol>
+            #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. -->
+                <iframe style="display:none" src="$flowExecutionUrl&_eventId=proceed"></iframe>
+            #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>
+            </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>
\ No newline at end of file
diff --git a/views/spnego-unavailable.vm b/views/spnego-unavailable.vm
new file mode 100644
index 0000000..3673f02
--- /dev/null
+++ b/views/spnego-unavailable.vm
@@ -0,0 +1,49 @@
+##
+## 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>
diff --git a/views/user-prefs.js b/views/user-prefs.js
new file mode 100644
index 0000000..ab994f9
--- /dev/null
+++ b/views/user-prefs.js
@@ -0,0 +1,45 @@
+"use strict";
+
+function createCookie(name, value, seconds) {
+    var date = new Date();
+    date.setTime(date.getTime() + (seconds * 1000));
+    var expires = "; expires=" + date.toGMTString();
+    
+    var path = '$environment.getProperty("idp.cookie.path", $request.getContextPath())';
+    if (path.length > 0)
+        path = "; path=" + path;
+    document.cookie = name + "=" + value + expires + path;
+}
+
+function eraseCookie(name) {
+    createCookie(name, "", -31536000);
+}
+
+function readCookie(name) {
+    var nameEQ = name + "=";
+    var ca = document.cookie.split(';');
+    for (var i = 0; i < ca.length; i++) {
+        var c = ca[i];
+        while (c.charAt(0) == ' ')
+            c = c.substring(1, c.length);
+        if (c.indexOf(nameEQ) == 0)
+            return c.substring(nameEQ.length, c.length);
+    }
+    return null;
+}
+
+function load(id) {
+    var checkbox = document.getElementById(id);
+    if (checkbox != null) {
+        var spnego = readCookie(checkbox.name);
+        checkbox.checked = (spnego == "1");
+    }
+}
+
+function check(checkbox) {
+    if (checkbox.checked) {
+        createCookie(checkbox.name, checkbox.value, $environment.getProperty("idp.cookie.maxAge","31536000"));
+    } else {
+        eraseCookie(checkbox.name);
+    }
+}
diff --git a/views/user-prefs.vm b/views/user-prefs.vm
new file mode 100644
index 0000000..8de0503
--- /dev/null
+++ b/views/user-prefs.vm
@@ -0,0 +1,60 @@
+##
+## Velocity Template for user preferences view
+##
+## Velocity context will contain the following properties
+## 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.userprefs.title", "Web Login Service") - #springMessageText("idp.userprefs.title.suffix", "Login Preferences")</title>
+    	<link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
+    	<script language="Javascript">
+    	<!--
+    	#parse( "user-prefs.js" )
+    	// -->
+    	</script>
+    </head>
+    <body onLoad="document.getElementById('content').style.display='block'; load('spnego')">
+    <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 Service") - #springMessageText("idp.userprefs.title.suffix", "Login Preferences")</h3>
+          <p>
+          #springMessage("idp.userprefs.info")
+          </p>
+        </header>
+
+        <noscript>
+          <div id="content" class="content">
+            $springMacroRequestContext.getMessage("idp.userprefs.no-js", "This feature requires Javascript.")
+          </div>
+        </noscript>
+        
+        <div id="content" class="content" style="display:none">
+          <div class="form-element-wrapper">
+          <h4>#springMessageText("idp.userprefs.options", "The following options are available:")</h4>
+          </div>
+
+          <div class="form-element-wrapper">
+            <input type="checkbox" id="spnego" name="_idp_spnego_autologin" value="1" onClick="check(this)">
+            #springMessageText("idp.userprefs.spnego", "Automatically try desktop login when available.")
+          </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>