Complex MFA Configuration - CSCfi/shibboleth-idp-authn-storage GitHub Wiki
Current File(s): conf/authn/mfa-authn-config.xml
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>