Contents
Overview
Claim Sets
* Incoming claim set
* Outgoing claim set
Claim Rules
Claim Rules For Claim Providers
* Acceptance Rules: accepting claims from claim provider trust
Claim Rules For Relying Parties
* Issuance Tranform Rules: issuing claims for relying party trust, e.g. send email as name id claim
* Issuance Authorization Rules: authorizing claims for relying party trust, e.g. permit all users
* Delegation Authorization Rules: impersonate users with an privileged account
Claim Rule Language
Syntax
* Each rule contains two parts:
– Condition statement (if true )
– Issuance statement (then issue/add claims)
* Operators:
Equal: ==
Assign: =
Regular Expression: =~
* For example:
# if incoming claim set contains # claim type "http://contoso.com/department" c:[Type == "http://contoso.com/department"] # then issue # claim type "http://adatum.com/department" # with the same value as incoming claim => issue[Type = "http://adatum.com/department", Value = c.Value);
Condition Statements
* Properties that can be checked:
– Type
– Value
– Issuer
– OriginalIssuer
– ValueType
* Examples:
# Check for Type only c:[Type == "http://contoso.com/department"] => issue[Type = "http://adatum.com/department", Value = c.Value); # Check for both Type and Value c:[Type == "http://contoso.com/department" Value == "Sales"] => issue[Type = "http://adatum.com/department", Value = c.Value); # Blank or missing condition statement means always true => issue[Type = "http://adatum.com/department", Value = c.Value);
Issuance Statements
* Two types:
– Add: adds claim to incoming claim set
– Issue: adds cliam to outgoing claim set
* Issue examples:
# Issue a claim with # type: "http://adatum.com/department" # value: "Sales" => issue[Type = "http://adatum.com/department", Value = "Sales"); # Issue incoming claim as is c:[Type == "http://contoso.com/department"] => issue(claim = c); # Issue all available claims c:[] => issue(claim = c);
* Add examples:
# Add a claim with # type: "http://adatum.com/department" # value: "Sales" => add[Type = "http://adatum.com/department", Value = "Sales");
Multiple Conditions
* AND multiple conditions: &&
* OR multiple conditions: create separate claims
* Combine multiple values: +
* Examples:
# If incoming claim set contains both # claim type: "http://contoso.com/location" # and cliam type: "http://contoso.com/role" c1:[Type == "http://contoso.com/location"] && c2:[Type == "http://contoso.com/role"] # Then issue a claim # type: "http://adatum.com/role" # value: c1.Value + " " + c2.Value => issue(Type = "http://adatum.com/role", Value = c1.Value + " " + c2.Value);
Aggregate Functions
EXISTS
* Check for the existence of a claim type without regard to number of times it finds
* Examples:
# Check for existence, i.e. any occurrance, of emailaddress claim type EXISTS([type == "http://contoso.com/emailaddress"]) # Then issue a single role claim type => issue(type = "http://contoso.com/role", value="Exchange User");
NOT EXISTS
* Check for the abstence of a claim type
* Examples:
# If location claim type does not exist NOT EXISTS([type == "type://contoso.com/location"]) # Then add location claim type with value of "Unknown" => add(type = "http://contoso/location", vlaue = "Unknown"); # If use does not have a group claim with value "ADFSUser" NOT EXISTS([type == "http://contoso.com/group", Value =~ "^(?!)ADFSUser"]) $ Then deny user access => issue(type = "http://schemas.microsoft.com/authorization/claims/deny", value="DenyUsersWithClaim");
COUNT
* Count the number of occurance of a claim type
* Examples:
# If you have multiple email address claims COUNT([type == "http://contoso.com/emailaddress"]) >= 2 # Then issue a MultipleEmails claim with value true => issue(type="http://contoso.com/Multipleemails", value="True");
RegEx
* Use =~ operator for regex, e.g.
# If role claim type value starts with CEO c:[type == "http://contoso.com/role", Value =~ "^CEO"] # Then issue claim as is => issue(claim = c);
RegEx Symbols
* Beginning of line: ^
* End of line: $
* Force case insensitive: (?!)
* OR values: |
# Pass through role claims that start with "ceo" or "coo", case insensitive c:[type == "http://contoso.com/role", Value =~ "^(?!)ceo|coo$"] =>issue(claim = c);
* Matches any characters zero or more times: .*
* Matches preceding character zero or more times: *
* Matches preceding character one or more times: +
Value =~ "(?!)DC.*Office" # matches "DC Office" or "DC Regional Office" etc. case insensitive Value =~ "(?!)yaho*" # matches "yah" or "yaho" or "yahoooooo" etc. case insensitive Value =~ "(?!)yaho+" # matches "yaho" (not "yah" though) or "yahoo" or "yahoooooo" etc. case insensitive
RegEx String Replacement
* Use RegExReplace function:
RegExReplace( "string_to_search", "string_to_match_regex_expression", "string_used_to_replace_matches)
* Examples
RegExReplace(c.Value, "(?!)directory","Manager"); # relace all matching occurrance of "directory" (case insensitive) with "Manager" so "IT Directory" will become "IT Manager"
Query Attribute Stores
* Default attribute store: Active Directory
* Also supports:
– SQL attribute stores
– LDAP attribute stores
SQL Attribute Stores
* If user is located in SQL database attribute store, claim rule language can
– query SQL database
– and generate claims based on the information in the database
* Can only use string type as input and/or output parameters
* Examples:
# If incoming claims contains emailaddress claim type c:[type == "http://contoso.com/emailaddress"] # Query SQL database for age and puchasinglimit using the emailaddress value as input parameter # and issue two outgoing claims using the values retured from database query # with "Custom SQL Store" as the issuer => issue(store="Custom SQL Store", types = ("http://contoso.com/age", "http://contoso.com/purchasinglimit"), query = "SELECT age,purchasinglimit FROM users WHERE email={0}", param = c.value);
LDAP Attribute Stores
* Format:
# For generic LDAP QUERY = "query_filter;" # For AD only QUERY = "QUERY_FILTER;ATTRIBUTES;DOMAIN_NAME\USERNAME" # If query_filter is missing, it defaults to: samAccountName={0}
* Examples:
# If incoming claims contains emailaddress claim type c:[type == "http://contoso.com/emailaddress"] # Query LDAP for age and puchasinglimit using the emailaddress value as input parameter # and issue two outgoing claims using the values retured from LDAP query # with "Custom LDAP Store" as the issuer => issue(store="Custom LDAP Store", types = ("http://contoso.com/age", "http://contoso.com/purchasinglimit"), query = "mail={0};age,purchasinglimit", param = c.value); # Extract memberOf using windowsaccountname to query AD c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] # add to working set claim type: "http://test.com/phase1" => add(store = "Active Directory", types = ("http://test.com/phase1"), query = ";memberOf;{0}", param = c.Value);
* Query Active Directory and send multiple claims in one query:
@RuleName = "Another example" c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"), query = ";mail,displayName,userPrincipalName,givenName,sn;{0}", param = c.Value);