...
In that case, the same user could end up having multiple different identifiers with the 2FA service, because whichever one they choose to enter at login would be the one sent. This can be solved addressed by using this attribute-based canonicalization, c14n method so that you ensure the same user identifier is sent to the 2FA service every time.
The following example illustrates how one could do this, where one has chosen to allow the user to enter either the value of their uid or their e-mail address as the username. Changes need to be made to all of the following, and sample config highlights the changes to each that would enable such. (One would also need to configure your authn handler to allow for either input, such as changing idp.authn.LDAP.userFilter to '(|(uid={user})(mail={user}))'.)
...
Code Block |
---|
<!-- Example LDAP Connector -->
<resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory" exportAttributes="uid"
ldapURL="ldap://localhost:10389"
baseDN="ou=People,dc=example,dc=edu"
principal="cn=admin,dc=example,dc=edu"
principalCredential="password">
<dc:FilterTemplate>
<![CDATA[
(|(uid=$resolutionContext.principal)(mail=$resolutionContext.principal))
]]>
</dc:FilterTemplate>
<dc:ReturnAttributes>uid</dc:ReturnAttributes>
</resolver:DataConnector> |
subject-c14n.
...
subject-c14n.properties
Code Block |
---|
|
idp.c14n.attribute.attributesToResolve = uid
idp.c14n.attribute.attributeSourceIds = uid |
subject-c14n.xml
Expand |
---|
|
Code Block |
---|
| <!-- at the bottom... -->
<bean id="shibboleth.c14n.attribute.PrincipalNameLookupStrategy"
parent="shibboleth.ContextFunctions.Scripted"
factory-method="inlineScript">
<constructor-arg>
<value>
<![CDATA[
var principalName = 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) {
principalName = princs.iterator().next().getName();
}
principalName;
]]>
</value>
</constructor-arg>
</bean> |
|
Expand |
---|
|
Code Block |
---|
| ...
<!-- Remove comment tags to enable Attribute-based c14n -->
<bean id="c14n/attribute" parent="shibboleth.PostLoginSubjectCanonicalizationFlow" />
...
<!-- at the bottom... -->
<bean id="shibboleth.c14n.attribute.PrincipalNameLookupStrategy"
parent="shibboleth.ContextFunctions.Scripted"
factory-method="inlineScript">
<constructor-arg>
<value>
<![CDATA[
var principalName = 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) {
principalName = princs.iterator().next().getName();
}
principalName;
]]>
</value>
</constructor-arg>
</bean> |
|
Reference
Expand |
---|
|
Bean ID | Type | Description |
---|
c14n/attribute-sourced 5.2 | AttributeSourcedSubjectCanonicalization | Built-in instance of this method, auto-configured by properties and other beans as described. V5.2+ allows reuse of this bean as a parent to define additional instances of this method with different settings. | c14n/attribute | SubjectCanonicalizationFlowDescriptor | Legacy definition of the original webflow-based version of this method, it was used “by example” as a commented bean in the original shipping default file | shibboleth.c14n.attribute.PrincipalNameLookupStrategy | Function<ProfileRequestContext,String> | Provides a principal name value for the AttributeResolutionContext during attribute resolution (i.e., $resolutionContext.principal will be set) | shibboleth.c14n.attribute.Transforms | Pair<String,String> | Pairs of regular expressions and replacement expressions to apply to the attribute-sourced username |
|
...