...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<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> |
...