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