String(resolutionContext.getAttributeRecipientID()) returns null

Andrew Morgan morgan at orst.edu
Mon Jul 17 18:19:35 EDT 2017


On Mon, 17 Jul 2017, Rhian Resnick wrote:

> Oh my, we may be missing something obvious. How does one obtain the 
> entityId of the remote service provider in the context of the mfa flow 
> selection?
>
>
> The value is populated by something because when Shibboleth resolves the 
> users attributes the value is present and the code executes as expected. 
> Unfortunately when called by the MFA selection code it is null.

I chose to implement a single attribute, "needs_duo", which drives the MFA 
logic.  Here is the bean in authn/mfa-authn-config.xml:

     <bean id="checkSecondFactor" parent="shibboleth.ContextFunctions.Scripted" factory-method="inlineScript"
         p:customObject-ref="shibboleth.AttributeResolverService">
         <constructor-arg>
             <value>
             <![CDATA[
                 nextFlow = null;

                 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");
                 if (! (mfaCtx.isAcceptable())) {
                     logger.debug('First factor is not enough - proceeding to Duo');
                     nextFlow = "authn/Duo";
                 }
                 else {
                     // other checks to see if Duo is required
                     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));

                     // Fetch attribute to check if Duo is required
                     resCtx.getRequestedIdPAttributeNames().add("needs_duo");
                     resCtx.resolveAttributes(custom);
                     attribute = resCtx.getResolvedIdPAttributes().get("needs_duo");
                     valueType =  Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
                     if (attribute != null && attribute.getValues().contains(new valueType("1"))) {
                         nextFlow = "authn/Duo";
                     }
                     input.removeSubcontext(resCtx);   // cleanup
                 }

                 nextFlow;   // pass control to second factor or end with the first
             ]]>
             </value>
         </constructor-arg>
     </bean>


Here is my "needs_duo" definition in attribute-resolver.xml:

     <!-- Duo -->
     <AttributeDefinition id="needs_duo" xsi:type="ScriptedAttribute">
         <Dependency ref="ONIDLDAP" />
         <Script><![CDATA[
             logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute.resolver.needs_duo");
             duoflag = "0";
             for (i=0; i < ismemberof.getValues().size(); i++) {
                 tmp = ismemberof.getValues().get(i);
                 if (tmp.toLowerCase().equals("cn=duo-opt-in,ou=duo,ou=app,ou=is,ou=org,ou=osu,ou=grouper,ou=groups,o=orst.edu")) {
                     logger.debug("User is opted-in to Duo");
                     duoflag = "1";
                 }
             }
             rpid = profileContext.getSubcontext("net.shibboleth.idp.profile.context.RelyingPartyContext").getRelyingPartyId();
             logger.debug("rpid=" + rpid);
             if (rpid.equals("http://people.oregonstate.edu/~morgan/simplesaml/module.php/saml/sp/metadata.php/default-sp")) {
                 duoflag = "1";
             }
             needs_duo.addValue(duoflag);
             logger.debug("needs_duo final value: " + needs_duo.getValues().get(0));
         ]]></Script>
     </AttributeDefinition>


This logic will require Duo if the user is a member of our duo-opt-in 
group or if the relying party is my test simplesaml installation.

 	Andy


More information about the users mailing list