Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagexml
    <util:map id="shibboleth.authn.MFA.TransitionMap">
        <!-- First rule runs the Password login flow. -->
        <entry key="">
            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/Password" />
        </entry>
        
        <!--
        Second rule runs a function if Password succeeds, to determine whether an additional
        factor is required.
        -->
        <entry key="authn/Password">
            <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">
        <constructor-arg>
            <value>
            <![CDATA[
                nextFlow = "authn/Duo";

                // Check if second factor is necessary for request to be satisfied.
                authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
                mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
                if (mfaCtx.isAcceptable()) {
                    nextFlow = null;
                }
                
                nextFlow;   // pass control to second factor or end with the first
            ]]>
            </value>
        </constructor-arg>
    </bean>

The additional setup will vary by version and is the process by which you associate the "internal" SAML AuthnContext class reference value with your second-factor method (Duo in this case) so that it can act as a signal.

Localtabgroup
Localtab live
activetrue
Expand
titleV4.1+

New (or modernized) installs of V4.1+ can be taught what context classes to associate with login flows using conf/authn/authn.properties:

conf/authn/authn.properties
Code Block
languagetext
...

idp.authn.Duo.supportedPrincipals = \
    saml2/http://example.org/ac/classes/mfa, \
    saml1/http://example.org/ac/classes/mfa

...

idp.authn.MFA.supportedPrincipals = \
    saml2/http://example.org/ac/classes/mfa, \
    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \
    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \
    saml1/http://example.org/ac/classes/mfa, \
    saml1/urn:oasis:names:tc:SAML:1.0:am:password
localtab-live
Expand
titleOlder Versions

Earlier versions rely on the conf/authn/general-authn.xml file to associate the class reference, using the supportedPrincipals property on the login flows. The class reference object must be connected to both the Duo and MFA flows because the latter is a superset of the former. The IdP is being told that these flows "support" this context class so it's necessary that both flows are told to do so. This is an excerpt (note the "..."'s) of the complete file and just the relevant aspects are shown; other settings will vary by local need.

conf/authn/general-authn.xml
Code Block
languagexml
<util:list id="shibboleth.AvailableAuthenticationFlows">
...
	<!-- Associates use of Duo with the local MFA context class. -->
    <bean p:id="authn/Duo" parent="shibboleth.AuthenticationFlow">
        <property name="supportedPrincipals">
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="http://example.org/ac/classes/mfa" />
            <bean parent="shibboleth.SAML1AuthenticationMethod"
                c:classRef="http://example.org/ac/classes/mfa" />
        </property>
    </bean>

...

	<!-- Associates MFA flow with both password- and Duo-based authentication. -->
    <bean p:id="authn/MFA" parent="shibboleth.AuthenticationFlow">
        <property name="supportedPrincipals">
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="http://example.org/ac/classes/mfa" />
            <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:classRef="http://example.org/ac/classes/mfa" />
            <bean parent="shibboleth.SAML1AuthenticationMethod"
                c:method="urn:oasis:names:tc:SAML:1.0:am:password" />
        </property>
    </bean>

...
</util:list>

...

The final step is to simply extend what's already been done to include the REFEDS context class so that SPs that need it can request it. This is a straight addition to the principal sets in the earlier examples, and the original values are included for completeness. You could also add the value as a SAML 1.1 option in an obvious way but that isn't likely to matter or come into play given that SAML 1.1 SPs, if they exist, can't actually request anything.

true
Localtabgroup
Localtab live
active
Expand
titleV4.1+
conf/authn/authn.properties
Code Block
languagetext
...

idp.authn.Duo.supportedPrincipals = \
	saml2/https://refeds.org/profile/mfa, \
    saml2/http://example.org/ac/classes/mfa, \
    saml1/http://example.org/ac/classes/mfa

...

idp.authn.MFA.supportedPrincipals = \
	saml2/https://refeds.org/profile/mfa, \
    saml2/http://example.org/ac/classes/mfa, \
    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport, \
    saml2/urn:oasis:names:tc:SAML:2.0:ac:classes:Password, \
    saml1/http://example.org/ac/classes/mfa, \
    saml1/urn:oasis:names:tc:SAML:1.0:am:password
localtab-live
Expand
titleOlder Versions
conf/authn/general-authn.xml
Code Block
languagexml
<util:list id="shibboleth.AvailableAuthenticationFlows">
...
	<!-- Associates use of Duo with the local MFA context class. -->
    <bean p:id="authn/Duo" parent="shibboleth.AuthenticationFlow">
        <property name="supportedPrincipals">
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="https://refeds.org/profile/mfa" />			<!-- REFEDS added here -->
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="http://example.org/ac/classes/mfa" />
            <bean parent="shibboleth.SAML1AuthenticationMethod"
                c:classRef="http://example.org/ac/classes/mfa" />
        </property>
    </bean>

...

	<!-- Associates MFA flow with both password- and Duo-based authentication. -->
    <bean p:id="authn/MFA" parent="shibboleth.AuthenticationFlow">
        <property name="supportedPrincipals">
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="https://refeds.org/profile/mfa" />			<!-- REFEDS added here -->
            <bean parent="shibboleth.SAML2AuthnContextClassRef"
                c:classRef="http://example.org/ac/classes/mfa" />
            <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:classRef="http://example.org/ac/classes/mfa" />
            <bean parent="shibboleth.SAML1AuthenticationMethod"
                c:method="urn:oasis:names:tc:SAML:1.0:am:password" />
        </property>
    </bean>

...
</util:list>

...