ADFS: Excluding a Specific User Group from MFA

Hi there, JJ Streicher-Bremer back again, this time talking about ADFS and multi-factor authentication. I had a need to configure an environment where everyone was required to use multi-factor authentication _except_ for folks in a specific AD group.

When looking at the ADFS 3.0 MFA configuration GUI there is a simple way to add users and groups to enforce the use of Multi Factor Authentication for specific users/groups.

So if I configured my ADFS to require MFA for all domain users, how might I exclude a set of users from this requirement?

What we don’t have via the GUI is an easy way to _exclude_ a user or group of users from the requirement of MFA.

The good news is there is a fairly simple way to make this happen, and we get to use PowerShell to do it!

First step is to define a few things:

  1. The default group that holds users who will _get_ MFA. In my case I’m using “Domain Users” because I want to have everyone using MFA for authentication
  2. The group that will specify the users who will be excluded from using MFA. In my case I created a group called “No MFA for these users” in my AD

When I started down this path I was pointed to an amazing blog post by Ramiro Calderon here:

https://blogs.msdn.microsoft.com/ramical/2014/01/30/under-the-hood-tour-on-multi-factor-authentication-in-adfs-part-1-policy/

Ramiro does a really great job of describing how the claims engine and pipeline work along with good descriptions on the claims themselves. This really jumpstarted the whole process. Thanks Ramiro!

After reading (and re-reading) the above blog post I determined I needed to come up with a rule that said something like this:

If a user is a member of “Domain Users” but _not_ a member of the group “No MFA for these users”, enforce the use of Multi Factor Authentication. Since the ADFS claims rules engine does not understand group (or user) names directly, we have to convert those into SIDs. That can be accomplished via ADUC or through PowerShell (get-adgroup “domain users”).

When we break down the pieces we have

  • A member of “Domain Users” becomes: [Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value == “S-1-5-21-3755518198-905394505-1163020732-513”]
  • A member of “No MFA for these users” becomes: [Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value == “S-1-5-21-3755518198-905394505-1163020732-15115”]
  • Enforce the use of MFA becomes: Type = “http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod”, Value = “http://schemas.microsoft.com/claims/multipleauthn”

Putting it all together our rule would look like:

exists([Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value == “S-1-5-21-3755518198-905394505-1163020732-513”]) && NOT exists([Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid”, Value == “S-1-5-21-3755518198-905394505-1163020732-15115”]) => issue (Type = “http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod”, Value = “http://schemas.microsoft.com/claims/multipleauthn”);

Now that I knew the claims rules I wanted to use I just had to figure out how to get them into ADFS. In the ADFS GUI there is no way to directly edit the rules so PowerShell to the rescue! Since I was using PowerShell I started using variables. My rule then looked like this:

$GroupAddMFA = Get-ADGroup “domain users”

$GroupAddNoMFA = get-adgroup “no MFA for these users”

$GroupMfaClaimTriggerRule = ‘exists([Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid“, Value == “‘ + $groupAddMFA.SID.Value + ‘“]) && NOT exists([Type == “http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid“, Value == “‘ + $groupAddNoMFA.SID.Value + ‘“]) => issue (Type = “http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod“, Value = “http://schemas.microsoft.com/claims/multipleauthn“);’

I wanted to add these rules to the relying party trust for O365, so I put that object into a variable too.

$rp = Get-AdfsRelyingPartyTrust -name “Microsoft Office 365 Identity Platform”

Before I actually modified the rules I had to remove the groups from the “Global Multi-Factor Authentication Policy”, but leave the checkbox enabling the MFA provider.

Now I had to add my ruleset to the “Additional Authentication Rules” for my relying party trust:

Set-AdfsRelyingPartyTrust –TargetRelyingParty $rp –AdditionalAuthenticationRules $GroupMfaClaimTriggerRule

Once I set this up all the users in my lab domain were forced to use MFA, except for those uses in the “No MFA for these users”.

Even better news is that in Server 2016 we should be able to accomplish all this via the “Access Control Policies” GUI directly:

I hope this blog post helps to explain by example some simple ADFS claims rules and how to load those rules into ADFS 3.0 as well as something to look forward to in Server 2016.