Hello, Joji Oshima here to dive deeper into the Claims Rule Language for AD FS. A while back I wrote a getting started post on the claims rule language in AD FS 2.0. If you haven’t seen it, I would start with that article first as I’m going to build on the claims rule language syntax discussed in that earlier post. In this post, I’m going to cover more complex claim rules using Regular Expressions (RegEx) and how to use them to solve real world issues.

–

An Introduction to Regex

The use of RegEx allows us to search or manipulate data in many ways in order to get a desired result. Without RegEx, when we do comparisons or replacements we must look for an exact match. Most of the time this is sufficient but what if you need to search or replace based on a pattern? Say you want to search for strings that simply start with a particular word. RegEx uses pattern matching to look at a string with more precision. We can use this to control which claims are passed through, and even manipulate the data inside the claims.

–

Using RegEx in searches

Using RegEx to pattern match is accomplished by changing the standard double equals "==" to "=~" and by using special metacharacters in the condition statement. I’ll outline the more commonly used ones, but there are good resources available online that go into more detail. For those of you unfamiliar with RegEx, let’s first look at some common RegEx metacharacters used to build pattern templates and what the result would be when using them.

Pass through any employeeId claims that contain start with at least one "0"

*

Match preceding character zero or more times

Similar to above, more useful in RegExReplace() scenarios.

Table 1: RegEx Metacharacters

–

Using RegEx in string manipulation

RegEx pattern matching can also be used in replacement scenarios. It is similar to a "find and replace", but using pattern matching instead of exact values. To use this in a claim rule, we use the RegExReplace() function in the value section of the issuance statement.

The RegExReplace() function accepts three parameters:

The first is the string in which we are searching.

We will typically want to search the value of the incoming claim (c.Value), but this could be a combination of values (c1.Value + c2.Value).

The second is the RegEx pattern we are searching for in the first parameter

Pass through any role claims. If any of the claims contain the word "Director", RegExReplace() will change it to "Manager". For example, "Director of Finance" would pass through as "Manager of Finance".

–

Real World Examples

Let’s look at some real world examples of regular expressions in claims rules.

–

# Problem 1:

We want to add claims for all group memberships, including distribution groups.

–

# Solution:

Typically, group membership is added using the wizard and selecting Token-Groups Unqualified Names and map it to the Group or Role claim. This will only pull security groups, not distribution groups, and will not contain Domain Local groups.

Get the groups in naming format, with or with the (long) domain name (depends on which token groups was used)

</COMMENT BY JORGE>

–

We can pull from memberOf, but that will give us the entire distinguished name, which is not what we want. One way to solve this problem is to use three separate claim rules and use RegExReplace() to remove unwanted data.

Example: We process the value in phase 2 claim and put "Group1" into the role claim

Digging Deeper: RegExReplace(c.Value, "^CN=", "")

c.Value is the value of the phase 1 claim. This is what we are searching in.

"^CN=" is the RegEx syntax used to find "CN=" at the beginning of the string.

"" is the replacement value. Since there is no string, it effectively removes any matches.

–

# Problem 2:

We need to compare the values in two different claims and only allow access to the relying party if they match.

–

# Solution:

In this case we can use RegExReplace(). This is not the typical use of this function, but it works in this scenario. The function will attempt to match the pattern in the first data set with the second data set. If they match, it will issue a new claim with the value of "Yes". This new claim can then be used to grant access to the relying party. That way, if these values do not match, the user will not have this claim with the value of "Yes".

Example: If there is a data1 claim with the value of "contoso" and a data2 claim with a value of "contoso", it will issue a UserAuthorized claim with the value of "Yes". However, if data1 is "adatum" and data2 is "fabrikam", it will issue a UserAuthorized claim with the value of "adatum".

Digging Deeper: RegExReplace(c1.Value, c2.Value, "Yes")

c1.Value is the value of the data1 claim. This is what we are searching in.

c2.Value is the value of the data2 claim. This is what we are searching for.

"Yes" is the replacement value. Only if c1.Value & c2.Value match will there be a pattern match and the string will be replaced with "Yes". Otherwise the claim will be issued with the value of the data1 claim.

–

# Problem 3:

Let’s take a second look at potential issue with our solution to problem 2. Since we are using the value of one of the claims as the RegEx syntax, we must be careful to check for certain RegEx metacharacters that would make the comparison mean something different. The backslash is used in some RegEx metacharacters so any backslashes in the values will throw off the comparison and it will always fail, even if the values match.

–

# Solution:

In order to ensure that our matching claim rule works, we must sanitize the input values by removing any backslashes before doing the comparison. We can do this by taking the data that would go into the initial claims, put it in a holding attribute, and then use RegEx to strip out the backslash. The example below only shows the sanitization of data1, but it would be similar for data2.

Example: We process the value in the data1holder claim and put "ContosoJohn" in a data1 claim

Digging Deeper: RegExReplace(c.Value,"\\","")

c.Value is the value of the data1 claim. This is what we are searching in.

"\\" is considered a single backslash. In RegEx, using a backslash in front of a character makes it a literal backslash.

"" is the replacement value. Since there is no string, it effectively removes any matches.

An alternate solution would be to pad each backslash in the data2 value with a second backslash. That way each backslash would be represented as a literal backslash. We could accomplish this by using RegExReplace(c.Value,"\\","\\") against a data2 input value.

–

# Problem 4:

Employee numbers vary in length, but we need to have exactly 9 characters in the claim value. Employee numbers that are shorter than 9 characters should be padded in the front with leading zeros.

–

# Solution:

In this case we can create a buffer claim, join that with the employee number claim, and then use RegEx to use the right most 9 characters of the combined string.

–

Phase 1: Create a buffer claim to create the zero-padding

=> add(Type = "Buffer", Value = "000000000");

–

Phase 2: Pull the employeeNumber attribute from Active Directory, place it in a holding claim

"^0*" finds any leading zeros. This is what we are searching for. If we only had ^0 it would only match a single leading zero. If we had 0* it would find any zeros in the string.

"" is the replacement value. Since there is no string, it effectively removes any matches.

–

Conclusion

As you can see, RegEx adds powerful functionality to the claims rule language. It has a high initial learning curve, but once you master it you will find that there are few scenarios that RegEx can’t solve. I would highly recommend searching for an online RegEx syntax tester as it will make learning and testing much easier. I’ll continue to expand the TechNet wiki article so I would check there for more details on the claims rule language.

[…] The guys from the ASKDS Team Blog have written another great article about the Claims Rule Language in ADFS. Kudos and credits of course go to the writer of the post on the AskDS Team Blog. Other articles about the claims rules language can be found through the following links: (2011-10-24) AD FS 2.0 Claims Rule Language Primer From The ASKDS Team and (2013-06-15) AD FS 2.0 Claims Rule Language Primer From The ASKDS Team (Part 2) […]