IDP 3.3: MFA validation and activationCondition problem
Philip Brusten
philip.brusten at kuleuven.be
Tue Jan 17 03:53:34 EST 2017
Hi
I think you were experiencing the same problem as I had.
Perhaps it's not exactly what you are looking for, but I am evaluating
the SPNEGO activationCondition in my script as Scott suggested. If
SPNEGO for some reason fails (e.g. misconfigured browser), this is
catched (event: ReselectFlow) and fallback to authn/Password.
Our SPNEGO activation condition just checks if the client IP resides in
the correct subnet. We use the SPNEGOAutoLoginManager to check if the
user opted-in for SPNEGO.
<util:map id="shibboleth.authn.MFA.TransitionMap">
<entry key="">
<bean parent="shibboleth.authn.MFA.Transition"
p:nextFlowStrategy-ref="selectFirstFactor" />
</entry>
<entry key="authn/SPNEGO">
<bean parent="shibboleth.authn.MFA.Transition">
<property name="nextFlowStrategyMap">
<map>
<entry key="ReselectFlow" value="authn/Password" />
<entry key="proceed" value-ref="checkSecondFactor" />
</map>
</property>
</bean>
</entry>
<entry key="authn/Password">
<bean parent="shibboleth.authn.MFA.Transition"
p:nextFlowStrategy-ref="checkSecondFactor" />
</entry>
<!-- An implicit final rule will return whatever the final flow
returns. -->
</util:map>
<import resource="../../system/flows/authn/spnego-authn-beans.xml" />
<util:map id="customObjectsToSelectFirstFactor">
<entry key="SPNEGOAutoLoginManager"
value-ref="SPNEGOAutoLoginManager" />
<entry key="SPNEGOActicationCondition"
value-ref="shibboleth.SPNEGO.ActivationCondition" />
</util:map>
<!-- See which first factor we can use (SPNEGO or Password) -->
<bean id="selectFirstFactor"
parent="shibboleth.ContextFunctions.Scripted"
factory-method="inlineScript"
p:customObject-ref="customObjectsToSelectFirstFactor">
<constructor-arg>
<value>
<![CDATA[
nextFlow = 'authn/Password';
logger =
Java.type("org.slf4j.LoggerFactory").getLogger("selectFirstFactor");
logger.debug('Starting selectFirstFactor');
authCtx =
input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
mfaCtx =
authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
//check to see if user opt-in for SPNEGO using cookie
SPNEGOAutoLoginManager = custom.get("SPNEGOAutoLoginManager");
isSPNEGOOptIn = SPNEGOAutoLoginManager.isEnabled();
logger.debug('Check if SPNEGO opt-in was done through cookie: '
+ isSPNEGOOptIn );
//check to see if SPNEGO can be activated
SPNEGOActicationCondition =
custom.get("SPNEGOActicationCondition");
isSPNEGOActivated = SPNEGOActicationCondition.apply(input);
logger.debug('Check if SPNEGO can be activated: ' +
isSPNEGOActivated );
if (SPNEGOAutoLoginManager.isEnabled() &&
SPNEGOActicationCondition.apply(input)) {
logger.debug('Opt-in for SPNEGO and activationcondition is
set');
nextFlow = 'authn/SPNEGO';
}
nextFlow;
]]>
</value>
</constructor-arg>
</bean>
<bean id="checkSecondFactor"
parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
p:customObject-ref="shibboleth.AttributeResolverService">
<constructor-arg>
<value>
<![CDATA[
nextFlow = 'authn/multifactor';
logger =
Java.type("org.slf4j.LoggerFactory").getLogger("checkSecondFactor");
logger.debug('Starting checkSecondFactor');
// 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");
//check is the current MFA-conftext is already acceptable,
if so check if the user did an opt-in, otherwise finish (with value 'null')
if (mfaCtx.isAcceptable()) {
logger.debug('MFA context is already acceptable but now
we will check if there is an opt-in set for multifactor');
// Attribute check is required to decide if first
factor alone is enough.
resCtx = input.getSubcontext(
"net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext",
true);
resCtx.setPrincipal(input.getSubcontext(
"net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName());
logger.debug('resolving attrs for ' +
input.getSubcontext("net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName());
resCtx.getRequestedIdPAttributeNames().add("eduPersonAssurance");
resCtx.resolveAttributes(custom);
// Check for an attribute that authorizes use of first
factor.
attribute =
resCtx.getResolvedIdPAttributes().get("eduPersonAssurance");
valueType =
Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
// set the nextFlow to null and exit MFA-flow when:
// a: There are no values for
eduPersonAssurance(attribute==null) -> not true in case of opt-in
// b: eduPersonAssurance is set, but does not contain
'MobileTwoFactorContract' -> not true in case of opt-in
if (attribute == null || (attribute != null && !
attribute.getValues().contains(new
valueType("urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract"))))
{
nextFlow = null;
}
input.removeSubcontext(resCtx); // cleanup
}
nextFlow; // pass control to second factor or end with
the first
]]>
</value>
</constructor-arg>
</bean>
Regards,
Philip
On 13/01/2017 17:52, Koch, Ken wrote:
>
> Thanks all in advance...
>
> Two reasons for this email:
>
> - Seeking validation of how we’re using the new MFA
>
> - Help with general-authn.xml SPNEGO activationCondition not firing
> when MFA is enabled
>
> Our intended authN flow:
>
> - authn/SPNEGO when activation condition satisfied
>
> - authn/Password if not
>
> - authn/CustomDuo(s) when SP specifies an authNContextClassRef that
> matches
>
> Normally, I’d abbreviate the config but with so many people
> transitioning to the new MFA router on 3.3 I figured this may be
> helpful IF it’s correct.
>
> The MFA flow works in our testing, but we want to make sure we’re
> implementing according to the intended purposes and specs.
>
> *Problem*: The activationCondition in the general-authn.xml for SPNEGO
> is NOT firing. SPNEGO works fine, but throws SPNEGO unavailable
> exceptions rather than adhering to the activationCondition logic. If
> we reference SPNEGO directly in idp.properties, it works just fine.
> When we call it via MFA, IDP ignores the activationCondition but uses
> the SPNEGO flow. What did we do wrong?
>
> Configuration examples below.
>
> Our mfa-authn-config.xml:
>
> <util:map id="shibboleth.authn.MFA.TransitionMap">
>
> <entry key="">
>
> <bean parent="shibboleth.authn.MFA.Transition"
> p:nextFlowStrategy-ref="checkSPNEGO" />
>
> </entry>
>
> <entry key="authn/SPNEGO">
>
> <bean parent="shibboleth.authn.MFA.Transition">
>
> <property name="nextFlowStrategyMap" >
>
> <map>
>
> <entry key="ReselectFlow" value="authn/Password" />
>
> <entry key="proceed" value-ref="checkSecondFactor" />
>
> </map>
>
> </property>
>
> </bean>
>
> </entry>
>
> <entry key="authn/Password">
>
> <bean parent="shibboleth.authn.MFA.Transition"
> p:nextFlowStrategy-ref="checkSecondFactor" />
>
> </entry>
>
> </util:map>
>
> <bean id="checkSPNEGO" parent="shibboleth.ContextFunctions.Scripted"
> factory-method="inlineScript"
> p:customObject-ref="shibboleth.HttpServletRequest">
>
> <constructor-arg>
>
> <value>
>
> <![CDATA[
>
> var logger =
> Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.authn.impl.TransitionMultiFactorAuthentication");
>
> logger.debug("MFA SPNEGO: Invoking SPNEGO");
>
> nextFlow = "authn/SPNEGO";
>
> nextFlow;
>
> ]]>
>
> </value>
>
> </constructor-arg>
>
> </bean>
>
> <!-- Decide if and where to route the Duo requirement to. -->
>
> <bean id="checkSecondFactor"
> parent="shibboleth.ContextFunctions.Scripted"
> factory-method="inlineScript"
> p:customObject-ref="shibboleth.HttpServletRequest">
>
> <constructor-arg>
>
> <value>
>
> <![CDATA[
>
> var logger =
> Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.authn.impl.TransitionMultiFactorAuthentication");
>
> logger.debug("MFA checkSecondFactor: Beginning decision logic.");
>
> nextFlow = null;
>
> // Setup the context classes to check status
>
> authCtx =
> input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");
>
> mfaCtx =
> authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");
>
> // Make sure it's not null
>
> if (mfaCtx != null) {
>
> // Check if the authContextPolicy or weighting has been
> satisfied
>
> if (mfaCtx.isAcceptable()) {
>
> logger.debug("MFA checkSecondFactor: Policies satisfied");
>
> } else {
>
> // Setup a new default nextFlow to the duo fully-enforced
>
> nextFlow = "authn/duo_washu2fa_all_networks";
>
> // We need more than the basic stuff, so setup some data
>
> rpCtx =
> authCtx.getSubcontext("net.shibboleth.idp.authn.context.RequestedPrincipalContext");
>
> if (rpCtx != null) {
>
> // Grab the authNContextClass principals that came in
> the SAML request
>
> rps = rpCtx.getRequestedPrincipals();
>
> // Define our own principals to use for matching
>
> var AuthnContextClassRefPrincipal =
> Java.type("net.shibboleth.idp.saml.authn.principal.AuthnContextClassRefPrincipal");
>
> authCtxClass_external_networks = new
> AuthnContextClassRefPrincipal("external_networks");
>
> // No need to use this next one because we'll default
> to it
>
> // authCtxClass_all_networks = new
> AuthnContextClassRefPrincipal("all_networks");
>
> // Check for a match
>
> if (rps.contains(authCtxClass_external_networks)) {
>
> // Pick the duo app for off campus
>
> logger.debug("MFA checkSecondFactor: Selected external_networks");
>
> nextFlow = "authn/duo_external_networks";
>
> }
>
> }
>
> }
>
> }
>
> nextFlow;
>
> ]]>
>
> </value>
>
> </constructor-arg>
>
> </bean>
>
> general-authn.xml
>
> <bean id="shibboleth.SPNEGO.ActivationCondition"
> parent="shibboleth.Conditions.Scripted" factory-method="inlineScript"
> p:customObject-ref="shibboleth.HttpServletRequest">
>
> <constructor-arg>
>
> <value>
>
> <![CDATA[
>
> var logger =
> Java.type("org.slf4j.LoggerFactory").getLogger("shibboleth.SPNEGO.ActivationCondition");
>
> logger.debug("GenAuth SPNEGO: Beginning decision logic.");
>
> … Ommitting cookie and x-forwarded-for IP segment checking, returns
> true|false …
>
> ]]>
>
> </value>
>
> </constructor-arg>
>
> </bean>
>
> <bean id="authn/SPNEGO" parent="shibboleth.AuthenticationFlow"
> p:nonBrowserSupported="false"
> p:activationCondition-ref="shibboleth.SPNEGO.ActivationCondition">
>
> <property name="supportedPrincipals">
>
> <list>
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod”
> c:method="urn:ietf:rfc:1510" />
>
> </list>
>
> </property>
>
> </bean>
>
> <bean id="authn/duo_washu2fa_all_networks"
> parent="shibboleth.AuthenticationFlow"
> p:forcedAuthenticationSupported="true" p:nonBrowserSupported="false">
>
> <property name="supportedPrincipals">
>
> <list>
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="all_networks" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod"
> c:method="all_networks" />
>
> </list>
>
> </property>
>
> </bean>
>
> <bean id="authn/duo_washu2fa_external_networks"
> parent="shibboleth.AuthenticationFlow"
> p:forcedAuthenticationSupported="true" p:nonBrowserSupported="false">
>
> <property name="supportedPrincipals">
>
> <list>
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="external_networks" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod"
> c:method="external_networks" />
>
> </list>
>
> </property>
>
> </bean>
>
> <bean id="authn/MFA" parent="shibboleth.AuthenticationFlow"
> p:passiveAuthenticationSupported="true"
> p:forcedAuthenticationSupported="true">
>
> <property name="supportedPrincipals">
>
> <list>
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol" />
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
> />
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Password" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod"
> c:method="urn:oasis:names:tc:SAML:1.0:am:password" />
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="all_networks" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod"
> c:method="all_networks" />
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="external_networks" />
>
> <bean parent="shibboleth.SAML1AuthenticationMethod"
> c:method="external_networks" />
>
> <bean parent="shibboleth.SAML2AuthnContextClassRef"
> c:classRef="urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos" />
>
> </list>
>
> </property>
>
> </bean>
>
> ____________________________________________________________
>
> *Ken Koch*| Infrastructure Architect, Enterprise Engineering
>
> Washington Universityin St. Louis
>
> 7425 Forsyth Blvd., Campus Box 1110 | St. Louis, MO 63105
>
> w 314-935-8315 | c 314-223-7256 | ken at wustl.edu <mailto:ken at wustl.edu>
>
> ------------------------------------------------------------------------
>
> The materials in this message are private and may contain Protected
> Healthcare Information or other information of a sensitive nature. If
> you are not the intended recipient, be advised that any unauthorized
> use, disclosure, copying or the taking of any action in reliance on
> the contents of this information is strictly prohibited. If you have
> received this email in error, please immediately notify the sender via
> telephone or return mail.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/users/attachments/20170117/c77be363/attachment-0001.html>
More information about the users
mailing list