Versions Compared

Key

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

...

Code Block
languagexml
titleConditional use of two factors, Flow1 and Flow2, based on user attribute
collapsetrue
<util:map id="shibboleth.authn.MFA.TransitionMap">
	<!-- Run authn/Flow1 first. -->
	<entry key="">
		<bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/Flow1" />
	</entry>

	<!--
	Second rule runs a function if authn/Flow1 succeeds, to determine whether an additional
	factor is required.
	-->
	<entry key="authn/Flow1">
		<bean parent="shibboleth.authn.MFA.Transition" p:nextFlowStrategy-ref="checkSecondFactor" />
	</entry>

	<!-- An implicit final rule will return whatever the second 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/Flow2";

            // 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
                usernameLookupStrategyClass = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");
                usernameLookupStrategy = new usernameLookupStrategyClass();
                resCtx.setPrincipal(usernameLookupStrategy.apply(input));


				// resolve the attribute to determine if a first factor is sufficient
                resCtx.getRequestedIdPAttributeNames().add("allowedLoginMethods");
                resCtx.resolveAttributes(custom);
                
                // Check for an attribute value 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("Flow1"))) {
                    nextFlow = null;
                }
                
                input.removeSubcontext(resCtx);   // cleanup
            }
            
            nextFlow;   // pass control to second factor or end with the first
        ]]>
	</value>
	</constructor-arg>
</bean>

...