It is important to understand claim sets as part of the claims pipeline. When claims come in, they are a part of the incoming claim set. After claims are processed by claim rules, they become part of the outgoing claim set. An important piece to understand is there is an incoming and outgoing claim set for the Claims Provider Trust and for the Relying Party Trust, so there are two places claims can be processed before leaving AD FS.
Read more about the claims pipeline here.
If the condition statement is true, the issuance statement will be executed. If the condition statement is false, the engine will move on to the next rule. Example: Simple Claims Rule Syntax
Condition statements look at all incoming claims and determine if there is one that matches the condition. The following properties can be queried in an incoming claim:
The format for querying an incoming claim is c:[query] where the variable c represents a claim in the incoming claim set. The query can be more specific and check for more than one property. See some of the examples below to get an idea of how the format works. The two examples below are not complete syntax, as they are missing the issuance statement. Example: Check for an incoming claim type http://contoso.com/department
There are two types of issuance statements to use.
The ADD issuance statement is used to add additional claims to the incoming claim set so that subsequent claim rules can use them for processing. The ISSUE issuance statement is used to add claims to the outgoing claim. Example: Issue a claim http://contoso.com/department to the outgoing claim set
Another possibility is to have multiple conditions, and if all conditions evaluate to true, run the issuance statement. Each condition is joined using the && special operator. There is not a logical OR operator. To accomplish an OR, create separate claim rules. Example: Check for an incoming claim type http://contoso.com/role with a value of Editor and separate incoming claim type http://contoso.com/role with a value of Manager. If both are found, issue a claim http://contoso.com/role with the value of Managing Editor
The values of each individual incoming claim can be accessed and joined using the special operator + in the issuance statement. Example: Check for an incoming claim type http://contoso.com/location and separate incoming claim type http://contoso.com/role. If both are found, issue a claim http://contoso.com/targetedrole combining the values of the incoming roles
Typical claims rules will issue an output claim for each match it finds. Aggregate functions will issue or add a single claim regardless of the number of matches. The EXISTS function serves this purpose. EXISTS Example: Claims rule without an Aggregate Function
Example: Claim Rule that uses the COUNT Aggregate Function
This claim rule will issue the claim if the user has two or more proxy address claims.
Regular Expressions (regex) can be used in the condition or issuance statements. In a condition statement, regex allows similar matches to evaluate true. In issuance statements, regex allows parts of the string values to be used in the outgoing claim. Regular Expressions use special characters to perform various tasks inside a string.
Active Directory is the default store created when AD FS 2.0 is installed. SQL attribute stores and LDAP attribute stores can also be defined. The condition statement remains the same, but the issuance statement changes depending on which attribute store is used.
If user data is located in a SQL database, the Claim Rule Language can query the database and generate claims based on the information in the database. Example: Claim rule using a SQL Attribute Store
If user data is located in a LDAP store, the Claim Rule Language can query it and generate claims based on the information in the store. Example: Claim rule using an LDAP Attribute Store
There are many good articles that supplement the data in this article.
AD FS 2.0 Content Map http://social.technet.microsoft.com/wiki/contents/articles/2735.aspx When to Use a Custom Claim Rule: http://technet.microsoft.com/en-us/library/ee913558(WS.10).aspx
The Role of the Claim Rule Language: http://technet.microsoft.com/en-us/library/dd807118(WS.10).aspx
The Role of the Claims Engine: http://technet.microsoft.com/en-us/library/ee913582(WS.10).aspx
Joji Oshima edited Revision 22. Comment: formatting
Richard Mueller edited Revision 29. Comment: Fixed duplicate <a name> tags in HTML so TOC works, added tags
Joji Oshima edited Revision 30. Comment: removed single quotes from an example
Joji Oshima edited Revision 9. Comment: formatting
This article was highlighted in the Top Contributors Awards - blogs.technet.com/.../top-contributors-awards-project-server-2013-outlook-sql-server-sharepoint-powershell-and-much-more.aspx
How do I read all the values of a given claim, http://contoso.com/role, and put them inside a comma delimited list like "Teacher, Student, Principle", so I can pass that list to a store procedure as shown on the sample below:
c1:[Type == "contoso.com/.../roles"] &&
c2:[type == "http://contoso.com/AppId"]
=> issue(store = "Some DB", types = ("schemas.xmlsoap.org/.../AppPermissions"),
query = "exec [dbo].[GetUserAppPermissions] {0}, {1}", param = List of all c1 values: "Teacher,Student,Principle", param = c2.value);
I would like to request that this very nice document be improved by either showing an example of a test for a false condition, or indicate that this is not possible. An example of testing for a false condition would be "if the user initiating the claim is NOT a member of SomeGroup, then send this attribute."
Christopher: This is covered under the "Aggregate Functions" section.
NOT EXISTS([type == "http://contoso.com/group"])
=> issue(type = "http://contoso/other", value = "Something");
GREAT Wiki, thanks for standing this up.
I had a need to do an OR check on an incoming claim. Rather than creating 5 rules to do this, I accomplished this with the following condition:
c:[Type == "<my incoming claim type>", Value =~ "^(value1|value2|value3|value3)"]
=> issue(Type = "my outgoing claim type", Value = "my desired role");
In the above example we check the value of the incoming claim type that begins with "value1" OR "value2" OR "value3" and if one or more of these values exist then we issue an outgoing claim with a value of "my desired role"
Can you clarify the QUERYsyntax for LDAP searches? This article states the format should be QUERY = "<query filter>;<attributes>" but when I try this I get an error from ADFS (EventID 111, POLICY3826) stating 'The LDAP query to the Active Directory attribute store must have three parts separated by semicolons. The first part is the LDAP filter query, the second part is a comma-separated list of LDAP attribute names, and the third part ist the user name in 'domain\user' format'.
My problem is I'm trying to authenticate users where the samAccountName doesn't match the UPN. The default claim template 'Send LDAP attributes as claim' seems hardcoded to use the samAccountName attribute (despite this being a throwback to the NT4 days) so I'm trying a custom claim rule as a workaround. The rule I'm trying is;
c:[Type == "schemas.microsoft.com/.../windowsaccountname"]
=> issue(
store = "Active Directory",
types = ("schemas.xmlsoap.org/.../emailaddress"),
query = "UserPrincipalName ={0};userPrincipalName,givenName,sn,mail", param = (c.Value)
);
How is the third field used? Is it required? If it's required and is fixed to domain\user format does that mean I can't use ADFS with an AD with mismatched samAccountName attributes? Are there any official docs on the claim rule language over and above your excellent and very useful blogposts?
Apologies for the long post and many questions - I'd planned to write a nice succint question!
Thanks,
Ed.