Introduction
The claims pipeline in ADFS is an interesting piece of software. I recently had a chance to re-familiarize myself with it. A third party SaaS application used an organizations internal employee numbers together with their own customer number for that organization to uniquely identify users. This called for issuing a claim to the SaaS app relying party (a.k.a. service provider) that picked up an attribute from Active Directory containing the internal employee numbers, prepending the SaaS app’s customer number and issuing it as a Name ID claim. Furthermore it was a requirement that the Name ID claim was the only custom claim issued. Of course I wanted the most elegant and efficient solution I could come up with, so that meant the the number of claims rules had to be as low as possible.
To do this kind of thing you have to use custom claim rules. The template rules are not flexible enough, but it is a good idea to use them to create the base claims query language syntax for you. Here is what I ended up with:
Get the employeeID LDAP attribute from Active Directory
c:[Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname”, Issuer == “AD AUTHORITY”]
=> add(store = “Active Directory”, types = (“http://langskip.no/employeeID”), query = “;employeeID;{0}”, param = c.Value);
This claim rule queries the Active Directory store for the employeeID attribute. If it is present a claim is added to the incoming claims pipeline by using the operator ADD. I store the value of employeeID in a custom type (https://langskip.no/employeeID) which only exists as a temporary placeholder for the value of employeeID. You can use both URLs and URIs to create custom claim types, if you don’t want to go with one of the standard ones. No claim is issued by this rule. That happens in the next rule…
Transform employeeID
c:[Type == “http://langskip.no/employeeID”]
=> issue(Type = “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”, Value = “350-00” + c.Value);
Next we check for the existence of an incoming claim of type http://langskip.no/employeeID. If it is present we now issue a claim of type nameidentifier. If the statement evaluates to False; no claim is issued. Hopefully the relying party knows what to do in that case. We set the value of the Name ID claim to the SaaS app’s customer ID number plus the employeeID from Active Directory.
The result looks like this in a test app I used for testing:
Claim Type |
Claim Value |
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier |
350-00123456 |
Thoughts on improvements…
I really would have wanted to accomplish this with just one claim rule. If anyone of you reading this knows how to accomplish that; sound off in the comments.
Happy authenticating!