<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 17, 2019 at 6:53 PM Cantor, Scott <<a href="mailto:cantor.2@osu.edu" target="_blank">cantor.2@osu.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 9/17/19, 3:20 PM, "users on behalf of Jeffrey Williams" <<a href="mailto:users-bounces@shibboleth.net" target="_blank">users-bounces@shibboleth.net</a> on behalf of <a href="mailto:jfwillia@uncg.edu" target="_blank">jfwillia@uncg.edu</a>> wrote:<br>
<br>
> David is correct.  Apologies for the lack of detail.  Any user, regardless of their MFA enrollment status, will encounter<br>
> that error when they try to log into an SP that is requesting the MFA profile.  Here is how our flow looks today(largely<br>
>> adapted from our 2.x environment that used this as a reference) <br>
<br>
I think you have the logic backwards.<br>
<br>
>                if (mfaCtx.isAcceptable()) {<br>
>                    // Attribute check is required to decide if first factor alone is enough.<br>
<br>
This conditional is (abstractly speaking) checking whether the SP is asking for anything beyond a password, but it's only executing your attribute logic if it *isn't*. So the SP asking for MFA is bypassing it.<br></blockquote><div><br></div><div>You are correct.  That is indeed (partially) the reverse of what I'd want.  I'd like for enrolled users to be presented with the Duo pane, regardless of what the SP requests.  However, if they're not enrolled and password is insufficient, throw an error.  Otherwise, complete successfully.   I played around with the logic a bit and came up with:</div><div><br></div><div> <font face="monospace">  nextFlow = null;<br><br>                //JFW: Adding logger per Shweta's comment<br>                logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute.resolver");<br><br>                // Go straight to second factor if we have to, or set up for an attribute lookup first.<br>                authCtx = input.getSubcontext("net.shibboleth.idp.authn.context.AuthenticationContext");<br>                mfaCtx = authCtx.getSubcontext("net.shibboleth.idp.authn.context.MultiFactorAuthenticationContext");</font></div><div><font face="monospace">                    //JFW: Negate and move mfaCtx.isAcceptable() to an else if after checking for enrollment.  <br>                    // Attribute check is required to decide if first factor alone is enough.<br>                    resCtx = input.getSubcontext(<br>                        "net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);<br>                    resCtx.setPrincipal(input.getSubcontext(<br>                        "net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName());<br>                    resCtx.getRequestedIdPAttributeNames().add("ADmemberOf");<br>                    resCtx.resolveAttributes(custom);<br><br>                    // Check for an attribute that authorizes use of first factor.<br>                    attribute = resCtx.getResolvedIdPAttributes().get("ADmemberOf");<br>                    valueType =  Java.type("net.shibboleth.idp.attribute.StringAttributeValue");</font></div><div><font face="monospace">                //JFW: regardless of what's requested from the SP, if the user is enrolled, present them with the Duo prompt<br>                if (attribute != null && attribute.getValues().contains(new valueType("CN=Duo_stagedactive2FA,OU=Duo,OU=apps,OU=groups,O=uncg"))) {<br>                        <a href="http://logger.info">logger.info</a>(" User in Duo_stagedactive2FA, Prompting for DUO ");<br>                        nextFlow = "authn/Duo";<br>                    } else if (!mfaCtx.isAcceptable()) {  //JFW: however, if they're not enrolled and password just isn't good enough...</font></div><div><font face="monospace">                                //JFW: I'd like to throw an error page up to the user, saying that the SP requires MFA in order to proceed<br>                                <a href="http://logger.info">logger.info</a>("SP requires MFA, of which this user is not enrolled.  Failing out");<br>                        }<br>                input.removeSubcontext(resCtx);   // cleanup<br><br><br>                nextFlow;   // pass control to second factor or end with the first<br></font><span style="font-family:monospace">               </span>  <br></div><div>I <i>think</i> this is doing what I intend, but I'd also like it to throw an error page on the IdP side if the SP requires MFA and the user is not enrolled.  Would I use a custom event as described here to handle that, or is there a better way(<a href="https://wiki.shibboleth.net/confluence/display/IDP30/AuthenticationConfiguration#AuthenticationConfiguration-CustomEvents">https://wiki.shibboleth.net/confluence/display/IDP30/AuthenticationConfiguration#AuthenticationConfiguration-CustomEvents</a>)?</div><div><br></div><div><br></div><div><br></div></div>-- <br><div dir="ltr" class="m_4291629243556048896gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><div dir="ltr">Jeffrey Williams </div><div dir="ltr">Identity Engineer<br>Identity & Access Services<br><a href="https://its.uncg.edu" target="_blank">https://its.uncg.edu</a></div></div><div dir="ltr"><br></div><div dir="ltr"><img src="https://uncgcdn.blob.core.windows.net/email/UNCGLogo.png"><br></div></div></div></div></div></div></div></div></div></div>