Versions Compared


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


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

	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" />

	<!-- An implicit final rule will return whatever the second flow returns. -->

<!-- Example script to see if second factor is required. -->
<bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
            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();

				// resolve the attribute to determine if a first factor is sufficient
                // 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