<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">
Ah, great. I just found the reference to CanonicalUsernameLookupStrategy in another thread but was struggling with the syntax on how to call it from within the script. I've updated my script and I believe that I have everything working properly now.
<div class=""><br class="">
</div>
<div class="">I also went ahead and updated the Wiki example on <a href="https://wiki.shibboleth.net/confluence/display/IDP30/MultiFactorAuthnConfiguration" class="">https://wiki.shibboleth.net/confluence/display/IDP30/MultiFactorAuthnConfiguration</a> under
"Programmatically Selecting Flows" to use this lookup method instead of the previous SubjectCanonicalizationContext method to hopefully save someone else in the future.</div>
<div class=""><br class="">
</div>
<div class="">-jeaton<br class="">
<div class=""><br class="">
<div>
<blockquote type="cite" class="">
<div class="">On Jan 24, 2017, at 9:04 AM, Scott Koranda <<a href="mailto:skoranda@gmail.com" class="">skoranda@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div class="">Hi,<br class="">
<br class="">
You can try something like this:<br class="">
<br class="">
logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp");<br class="">
<br class="">
// Determine the username <br class="">
usernameLookupStrategyClass = Java.type("net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy");<br class="">
usernameLookupStrategy = new usernameLookupStrategyClass();<br class="">
username = usernameLookupStrategy.apply(input);<br class="">
logger.debug("{} username is {}", logPrefix, username);<br class="">
<br class="">
// Resolve isMemberOf attribute for the authenticated user.<br class="">
resCtx = input.getSubcontext("net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext", true);<br class="">
resCtx.setPrincipal(username);<br class="">
resCtx.getRequestedIdPAttributeNames().add("isMemberOf");<br class="">
resCtx.resolveAttributes(custom);<br class="">
<br class="">
That class to find the username is new in 3.3.<br class="">
<br class="">
The above assumes Nashorn.<br class="">
<br class="">
Scott K<br class="">
<br class="">
<br class="">
<blockquote type="cite" class="">Hmm, close but not entirely there yet.<br class="">
<br class="">
I am occasionally, but not consistently, getting the following error:<br class="">
<br class="">
java.lang.RuntimeException: javax.script.ScriptException: TypeError: null has<br class="">
no such function "getPrincipalName" in <eval> at line number 10<br class="">
<br class="">
which corresponds to:<br class="">
<br class="">
resCtx.setPrincipal(input.getSubcontext(<br class="">
<br class="">
"net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getPrincipalName<br class="">
());<br class="">
<br class="">
so the SubjectCanonicalizationContext is coming back as null. It seems to only<br class="">
happen on a second trip through the IDP, when the first trip only used the<br class="">
first factor (auth/Password, using the stock JAAS password, backed against Krb5<br class="">
if that matters at all).<br class="">
<br class="">
The script I am using is exactly the one from the Wiki under "Conditional use<br class="">
of two factors" with authn/Password for Flow1, authn/Duo for Flow2, and the<br class="">
attribute name and value changed to eduPersonAssurance and<br class="">
"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"<br class="">
respectively (my eduPersonAssurance returns either that, or our custom Duo<br class="">
contact class of <a href="https://login.cmu.edu/duo" class="">https://login.cmu.edu/duo</a> )<br class="">
<br class="">
Any ideas? Is there a way to do any additional logging from the inline script<br class="">
to see why that context would be null?<br class="">
<br class="">
-jeaton<br class="">
<br class="">
<br class="">
On Jan 22, 2017, at 9:54 PM, Scott Koranda <<a href="mailto:skoranda@gmail.com" class="">skoranda@gmail.com</a>> wrote:<br class="">
<br class="">
<br class="">
Why is it just accepting the previous Password<br class="">
authentication and not checking the attribute (and then<br class="">
upgrading to Duo)?<br class="">
<br class="">
<br class="">
<br class="">
This was covered in the past few days in another thread with<br class="">
the subject "MFA result reuse with Duo". You can find where it<br class="">
begins at<br class="">
<br class="">
<a href="http://marc.info/?l=shibboleth-users&m=148476673200662&w=2" class="">http://marc.info/?l=shibboleth-users&m=148476673200662&w=2</a><br class="">
<br class="">
In short: <br class="">
<br class="">
Since the SP does not request a "MFA context" and you<br class="">
have not configured an override for that SP that requires an<br class="">
"MFA context", the IdP determines that your active authn/MFA flow<br class="">
result with the Password context satisifes the request. As<br class="">
such it does not re-run the authn/MFA flow and your strategy<br class="">
script never gets the chance to execute a second time for that<br class="">
user.<br class="">
<br class="">
You can change that behavior by setting<br class="">
<br class="">
idp.authn.favorSSO = false<br class="">
<br class="">
in idp.properties and then adding<br class="">
<br class="">
<property name="defaultAuthenticationMethods"><br class="">
<list><br class="">
<ref bean="MfaPrincipal" /><br class="">
<ref bean="PasswordPrincipal" /><br class="">
</list><br class="">
</property><br class="">
<br class="">
to either an override for that particular SP or to the<br class="">
DefaultRelyingParty<br class="">
in relying-party.xml, where<br class="">
<br class="">
<bean id="MfaPrincipal" parent="shibboleth.SAML2AuthnContextClassRef" <br class="">
c:classRef="<a href="https://refeds.org/profile/mfa" class="">https://refeds.org/profile/mfa</a>" /><br class="">
<br class="">
<bean id="PasswordPrincipal" parent=<br class="">
"shibboleth.SAML2AuthnContextClassRef" <br class="">
c:classRef=<br class="">
"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport" /><br class="">
<br class="">
(replace '<a href="https://refeds.org/profile/mfa" class="">https://refeds.org/profile/mfa</a>' with whatever you have<br class="">
configured your IdP to use as the MFA context).<br class="">
<br class="">
The order above is important--the "MfaPrincipal" must be first.<br class="">
<br class="">
With those changes, the IdP will run the authn/MFA flow if the user<br class="">
only has<br class="">
an active Password result.<br class="">
<br class="">
<br class="">
<br class="">
I have attempted to write this up. On this page<br class="">
<br class="">
<a href="https://wiki.shibboleth.net/confluence/display/IDP30/" class="">https://wiki.shibboleth.net/confluence/display/IDP30/</a><br class="">
MultiFactorAuthnConfiguration<br class="">
<br class="">
see the section "Reuse of the Entire authn/MFA Flow Result (Or<br class="">
When Is a MFA Next Flow Strategy Executed?)"<br class="">
<br class="">
Note that Scott Cantor has not had a chance to review the text<br class="">
yet.<br class="">
<br class="">
The technical details, however, have been verified by at least<br class="">
one other deployer (Josh O'Dowd) so it should work.<br class="">
<br class="">
If you have any comments on the text please let me know, or<br class="">
feel free to edit it yourself (it is, after all a wiki...)<br class="">
<br class="">
Thanks,<br class="">
<br class="">
Scott K<br class="">
<br class="">
<br class="">
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</div>
</body>
</html>