c14n attribute sourced subject, multiple principals

Joseph Fischetti Joseph.Fischetti at marist.edu
Wed Mar 18 16:47:09 EDT 2020

We're testing/evaluating Duo and one of the requirements for Duo is a reliable subject name.  We do allow our users to sign in with a number of unique attribute values, so our DataConnector and ldap search filter (in ldap.properties) is long, and an attribute sourced subject is necessary.

I have an MFA configuration that calls the password flow first, and then calls a script.  The c14n attribute sourced filter works just fine.

I've been asked to implement IP address whitelisting for MFA purposes, so I planned to try to use the built in authn/IPAddress flow (if possible... Otherwise I would need to check the IP address in my mfa flow script, or do the IP address whitelisting in Duo itself).  When I add authn/IPAddress to the mfa flow, the c14n ends up failing the last time it's called (right before getting passed back to the SP).  It's failing because there's more than one "princs" (I'm using a documentation provided script in the PrincipalNameLookupStrategy).

I'm going to try and track it down, but my inclination is that something adds a principal to the context, and the 3rd time through the canonicalization process there's more than one value to choose from.  The unmodified script in the PrincipalNameLookupStrategy is below [1].  I've added some logging to it and when I run it I get this [2].  Log's grep'ed for clarity.  That's during a *single* login event.  I'm assuming it runs c14n before the authn/IPAddress flow, before the authn/Duo flow, and before the final attribute resolution.  

MFA Transition map is included (in case it helps) [3]

Is there a better way to handle this (Both the subject, and the IP address gating)?

[1]   var principal = null;
        var subject = profileContext.getSubcontext("net.shibboleth.idp.authn.context.SubjectCanonicalizationContext").getSubject();
        var princs = subject.getPrincipals(Java.type("net.shibboleth.idp.authn.principal.UsernamePrincipal").class);

       if (princs.size() == 1) {
            principal = princs.iterator().next().getName();


2020-03-18 16:25:32,098 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:3] - Running c14 subject name canonicalization
2020-03-18 16:25:32,198 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:9] - princs.size = 1
2020-03-18 16:25:32,974 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:3] - Running c14 subject name canonicalization
2020-03-18 16:25:32,992 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:9] - princs.size = 1
2020-03-18 16:25:33,439 - DEBUG [net.shibboleth.idp.checkSecondFactor:37] - Running Duo Flow
2020-03-18 16:25:43,074 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:3] - Running c14 subject name canonicalization
2020-03-18 16:25:43,076 - DEBUG [net.shibboleth.idp.c14nPrincipalScript:9] - princs.size = 2

    <util:map id="shibboleth.authn.MFA.TransitionMap">
        <entry key="">
            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/Password" />
        <entry key="authn/Password">
            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlow="authn/IPAddress" />
        <entry key="authn/IPAddress">
            <bean parent="shibboleth.authn.MFA.Transition" p:nextFlowStrategy-ref="checkSecondFactor" />

More information about the users mailing list