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