When you’re establishing a relying party trust with a provider filtering group membership you send through your AD FS Farm is often a prerequisite, either for performance issues -so that the token is not too big- or for security reasons as you do not want your provider to know your organisation, in particular when Windows groups are used as a RBAC model.
Unfortunately, by default the wizard only proposes to
- send all the group memberships
- do a 1:1 filter or search and replace on a specified group.
When you have design your application so every role is a Windows group membership and your applications has multiple roles, the task can be tedious in a scenario where “Your App” may have dozen of roles and each user may have read, write, or whatever additional permission.
Fortunately, the wizard is just a prebuilt set of rules around the ADFS language to create and issue tokens. We can therefore build our own rules, and this will serve us as a quick introduction to the ADFS language.
To have some boiler plate examples of the ADFS language, you can always select the ‘View language’ button at the bottom left of pre-built rule:
In this case, we can such that such a rule is equivalent to a custom rule whose contents would be:
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]
=> issue(claim = c);
In this example the variable is named “c* and if it matches the type windowsaccountname, it is simply issued. On a general note, an ADFS rule is “Condition => Action”. If condition is empty, the action is always done.
The action can be:
- issue to issue the claim
- add to add a piece of claim to a store to issue later as you cannot “remove” something from a claim.
In our example to filter the group membership, we will:
- store all the claims corresponding to the group membership
- issue a claim if it is a group and starts with the name we want as we have decided that our RBAC model for the application make the group in form of ‘MyApp_XXX’
The first rule is then written
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
=> add(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/Group"), query = ";memberOf;{0}", param = c.Value);
Note the verb ‘add’ to add the data to our temporary claim store.
The second rule can be expressed as:
<pre class="lang:default decode:true " title="5.2 Filter group membership starting with MyApp_">c:[Type == "http://schemas.xmlsoap.org/claims/Group", Value =~ "^(?i)MyApp_"]
=> issue(claim = c);
Please note that the rule order is important, since we cannot change the store once the claim is issued
Needless to say that those 2 rules are managing the group membership part of the claims you’re going to send to your relying party. In most cases you may want to send other claims. A standard list could be:
- Windows Account Name (standard ADFS Rule)
- Name (standard ADFS Rule)
- Get Group Membership from LDAP Claims without domain name (Custom Rule)
- Filter group membership starting with MyApp_ (custom rule)