[External] Re: SP requesting MFA login

Shweta Kautia skautia at northcarolina.edu
Tue Sep 17 15:36:22 EDT 2019


I can't remember the exact error when i used the example you are using here. However, I had to add some logging to trace where the logic was breaking and ended up adding an attribute with a flag value, in the resolver file after checking for AD group membership there.

I don't have an explanation of why that worked instead of checking for the AD group in that if statement like in the example.

 //SK: Determine if the nextFlow should be DUO based on criteria or pass through
 nextFlow = null;

 //SK: Adding logger
 logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute.resolver");

....few lines below ...

//SK: Check if user is part of the AD group Shib-Employee-MFA, if not skip the DUO Flow.
                    if (attribute != null && attribute.getValues().contains(new valueType("1") ) ) {
                        logger.info(" User in Shib-Employee-MFA (needs_duo). Prompting for DUO ");
                        nextFlow = "authn/Duo";
                        logger.info(" User NOT IN Shib-Employee-MFA. Skipping for DUO ");


<!-- Duo flag attribute based on memberOf from AD -->
        <resolver:AttributeDefinition id="needs_duo" xsi:type="Script" xmlns="urn:mace:shibboleth:2.0:resolver:ad">
         <resolver:Dependency ref="myLDAP" />
             logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute.resolver.needs_duo");
             duoflag = "0";

             if (typeof memberOf == "undefined" || memberOf == null ){
                logger.debug("memberOf attribute is not defined or null. Setting duoFlag to 0.");
                duoflag = "0";

                 for (i=0; i < memberOf.getValues().size(); i++) {
                     tmp = memberOf.getValues().get(i);
                     if (tmp.toLowerCase().equals("cn=shib-employee-mfa<some other values here..>")) {
                         logger.debug("User is opted-in to Duo");
                         duoflag = "1";
            }//end else memberOf == null

            //check if the requesting SP/relying party should be prompted for DUO.
            rpid = profileContext.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext").getRelyingPartyId();
            logger.debug("rpid=" + rpid);
            if (rpid.equals("<entity_ID>")){
                    duoflag = "1";


            logger.debug("needs_duo final value: " + needs_duo.getValues().get(0));


Shweta Kautia

From: users <users-bounces at shibboleth.net> on behalf of Jeffrey Williams <jfwillia at uncg.edu>
Sent: Tuesday, September 17, 2019 3:20 PM
To: users at shibboleth.net <users at shibboleth.net>
Subject: [External] Re: SP requesting MFA login

[CAUTION: External email. Do not click links or open attachments unless verified. Send all suspicious email as an attachment to spam at northcarolina.edu<mailto:spam at northcarolina.edu>]

David is correct.  Apologies for the lack of detail.  Any user, regardless of their MFA enrollment status, will encounter that error when they try to log into an SP that is requesting the MFA profile.  Here is how our flow looks today(largely adapted from our 2.x environment that used this as a reference: https://wiki.shibboleth.net/confluence/pages/viewpage.action?pageId=32112643  )

    <util:map id="shibboleth.authn.MFA.TransitionMap">
        <!-- First rule runs the authn/Password login flow. -->
        <entry key="">
            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/Password" />

        Second rule runs a function if authn/Password succeeds, to determine whether an additional
        factor is required.
        <entry key="authn/Password">
<bean parent="shibboleth.authn.MFA.Transition" p:nextFlowStrategy-ref="checkSecondFactor" />

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

    <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
                nextFlow = null;

                // 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);

                    // Check for an attribute that authorizes use of first factor.
                    attribute = resCtx.getResolvedIdPAttributes().get("ADmemberOf");
                    valueType =  Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
                    if (attribute != null && attribute.getValues().contains(new valueType("CN=duoActiveUsers,OU=are,OU=here,O=uncg"))) {
                        nextFlow = "authn/Duo";

                    input.removeSubcontext(resCtx);   // cleanup

                nextFlow;   // pass control to second factor or end with the first

Based on it's behavior, it looks like it's making a non-proceed decision after the first factor without proceeding to the checkSecondFactor(where the MFA magic happens). I can provide more configs if it helps.

On Tue, Sep 17, 2019 at 12:58 PM Jeffrey Williams <jfwillia at uncg.edu<mailto:jfwillia at uncg.edu>> wrote:
I'm looking for guidance on the best approach to a request.

We're currently running 3.3.3 using the native Duo plugin and the IDP has only one flow. It's scripted to check to see if the user is enrolled in MFA before presenting authn/Duo.

We have a vendor using Shibboleth SP that we're looking to integrate with and one of the requirements is that authorized users must MFA into the service.  My first thought was to have the SP configured their  authnContextClassRef   to our MFA value ("https://refeds.org/profile/mfa").  However, it seems that the IdP's authentication flow short-circuits after 1FA and sends an error back to the SP saying:

SAML response reported an IdP error.
Error from identity provider:
Sub-Status: urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext
Message: An error occurred.
Status: urn:oasis:names:tc:SAML:2.0:status:Requester
With the following in the IdP logs:

2019-09-16 19:21:30,180 - INFO [net.shibboleth.idp.authn.impl.ValidateUsernamePasswordAgainstLDAP:152] - Profile Action ValidateUsernamePasswordAgainstLDAP: Login by 'jfwillia' succeeded
2019-09-16 19:21:30,191 - DEBUG [net.shibboleth.idp.session.impl.DetectIdentitySwitch:148] - Profile Action DetectIdentitySwitch: No previous session found, nothing to do
2019-09-16 19:21:30,191 - WARN [net.shibboleth.idp.authn.impl.FinalizeAuthentication:179] - Profile Action FinalizeAuthentication: Authentication result for flow authn/MFA did not satisfy the request
2019-09-16 19:21:30,195 - WARN [org.opensaml.profile.action.impl.LogEvent:105] - A non-proceed event occurred while processing the request: RequestUnsupported

This is regardless of MFA enrollment.

I checked through the docs and didn't find anything that seemed to answer the question.  Is there a way to maintain the single authentication flow and have it only authenticate MFA users for this SP?

Jeffrey Williams
Identity Engineer
Identity & Access Services


Jeffrey Williams
Identity Engineer
Identity & Access Services

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/users/attachments/20190917/2369971d/attachment.html>

More information about the users mailing list