Complex MFA Configuration - CSCfi/shibboleth-idp-authn-storage GitHub Wiki

Current File(s): conf/authn/mfa-authn-config.xml

Revocation and forceAuthn

To implement storage authentication revocation and for using Storage authentication a more complex MFA configurations is required. The example is a modified snippet from provided mfa-authn-config-example.xml file.

The example configuration resolves a attribute containing not-before timestamp in ms from epoch. Any authentication result issued before is considered not valid. NOTE! Missing still forceAuthn example.

<util:map id="shibboleth.authn.MFA.TransitionMap">

    <entry key="">
        <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/IPAddress" />
    </entry>

    <entry key="authn/IPAddress">
        <bean parent="shibboleth.authn.MFA.Transition" p:nextFlowStrategy-ref="doStorageWithRevocation" /> 
    </entry>

    <entry key="authn/storage">
        <bean parent="shibboleth.authn.MFA.Transition">
            <property name="nextFlowStrategyMap">
                <map>
                    <!-- If we do not have a storage event we perform password -->
                    <entry key="ReselectFlow" value="authn/Password" />
                </map>
            </property>
        </bean>
    </entry>

    <entry key="authn/Password">
        <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/store" />
    </entry>

    <!-- An implicit final rule will return whatever the final flow returns. -->
</util:map>

<!-- This example assumes attribute named "revok" is a string value parsable as long and interpreted as ms from epoch. -->
<bean id="doStorageWithRevocation" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
    p:customObject-ref="shibboleth.AttributeResolverService">
    <constructor-arg>
        <value>
        <![CDATA[
        nextFlow = "authn/storage";
        // Set up for an attribute lookup.
        authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
        mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
        // Attributes are needed for second factor.
        resCtx = input.getSubcontext(
        "net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);
        // Look up the username
        usernameLookupStrategyClass = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");
        usernameLookupStrategy = new usernameLookupStrategyClass();
        resCtx.setPrincipal(usernameLookupStrategy.apply(input));
        resCtx.getRequestedIdPAttributeNames().add("revok");
        resCtx.resolveAttributes(custom);
        //Pass the resolved attribute to context
        if (resCtx.getResolvedIdPAttributes().get("revok")!=null){
          stCtx = authCtx.getSubcontext("fi.csc.idp.authn.context.StorageAuthenticationContext", true);
          stCtx.setAuthenticationEventNotBefore(resCtx.getResolvedIdPAttributes().get("revok").getValues().get(0).getValue());
        }
        input.removeSubcontext(resCtx);
        nextFlow; // perform storage flow 
        ]]>
        </value>
    </constructor-arg>
⚠️ **GitHub.com Fallback** ⚠️