With the recent announcement of General Availability of the Azure AD Conditional Access policies in the Azure Portal, it is a good time to reassess your current MFA policies particularly if you are utilising ADFS with on-premises MFA; either via a third party provider or with something like Azure MFA Server.
Prior to conditional MFA policies being possible, when utilising on-premises MFA with Office 365 and/or Azure AD the MFA rules were generally enabled on the ADFS relying party trust itself.  The main limitation with this of course is the inability to define different MFA behaviours for the various services behind that relying party trust.  That is, within Office 365 (Exchange Online, Sharepoint Online, Skype for Business Online etc.) or through different Azure AD Apps that may have been added via the app gallery (e.g. ServiceNow, SalesForce etc.).  In some circumstances you may have been able to define some level of granularity utilising custom authorisation claims, such as bypassing MFA for activesync and legacy  authentication scenarios, but that method was reliant on special client headers or the authentication endpoints that were being used and hence was quite limited in its use.
Now with Azure AD Conditional Access policies, the definition and logic of when to trigger MFA can, and should, be driven from the Azure AD side given the high level of granularity and varying conditions you can define. This doesn’t mean though that you can’t keep using your on-premises ADFS server to perform the MFA, you’re simply letting Azure AD decide when this should be done.
In this article I’ll show you the method I like to use to ‘migrate’ from on-premises MFA rules to Azure AD Conditional Access.  Note that this is only applicable for the MFA rules for your Azure AD/Office 365 relying party trust.  If you are using ADFS MFA for other SAML apps on your ADFS farm, they will remain as is.

Summary

At a high level, the process is as follows:

  1. Configure Azure AD to pass ‘MFA execution’ to ADFS using the SupportsMFA parameter
  2. Port your existing ADFS MFA rules to an Azure AD Conditional Access (CA) Policy
  3. Configure ADFS to send the relevant claims
  4. “Cutover” the MFA execution by disabling the ADFS MFA rules and enabling the Azure AD CA policy

The ordering here is important, as by doing it like this, you can avoid accidentally forcing users with a ‘double MFA’ prompt.

Step 1:  Using the SupportsMFA parameter

The crux of this configuration is the use of the SupportsMFA parameter within your MSOLDomainFederationSettings configuration.
Setting this parameter to True will tell Azure AD that your federated domain is running an on-premises MFA capability and that whenever it determines a need to perform MFA, it is to send that request to your STS IDP (i.e. ADFS) to execute, instead of triggering its own ‘Azure Cloud MFA’.
To perform this step is a simple MSOL PowerShell command:

Set-MsolDomainFederationSettings -domain yourFederatedDomain.com -SupportsMFA $true

Pro Tip:  This setting can take up to 15-30 mins to take effect.  So make sure you factor in this into your change plan.  If you don’t wait for this to kick in before cutting over your users will get ‘double MFA’ prompts.

Step 2:  Porting your existing MFA Rules to Azure AD Conditional Access Policies

There’s a whole article in itself talking about what Azure AD CA policies can do nowadays, but for our purposes let’s use the two most common examples of MFA rules:

  1. Bypass MFA for users that are a member of a group
  2. Bypass MFA for users on the internal network*

Item 1 is pretty straight forward, just ensure our Azure AD CA policy has the following:

  • Assignment – Users and Groups:
    • Include:  All Users
    • Exclude:  Bypass MFA Security Group  (simply reuse the one used for ADFS if it is synced to Azure AD)

MFABypass1
Item 2 requires the use of the Trusted Locations feature.  Note that at the time of writing, this feature is still the ‘old’ MFA Trusted IPs feature hosted in the Azure Classic Portal.   Note*:  If you are using Windows 10 Azure AD Join machines this feature doesn’t work.  Why this is the case will be an article in itself, so I’ll add a link here when I’ve written that up.
So within your Azure AD CA policy do the following:

  • Conditions – Locations:
    • Include:  All Locations
    • Exclude:  All Trusted IPs

MFABypass2.png
Then make sure you click on Configure all trusted locations to be taken to the Azure Classic Portal.  From there you must set Skip multi-factor authentication for requests from federated users on my intranet
MFABypass3.png
This effectively tells Azure AD that a ‘trusted location’ is any authentication requests that come in with a InsideCorporateNetwork claim.
Note:  If you don’t use ADFS or an IDP that can send that claim, you can always use the actual ‘Trusted IP addresses’ method.
Now you can define exactly which Azure AD apps you want MFA to be enabled for, instead of all of them as you had originally.
MFABypass7.png
Pro Tip:  If you are going to enable MFA on All Cloud Apps to start off with, check the end of this article for some extra caveats you should consider for, else you’ll start breaking things.
Finally, to make this Azure AD CA policy actually perform MFA, set the access controls:
MFABypass8.png
For now, don’t enable the policy just yet as there is more prep work to be done.

Step 3:  Configure ADFS to send all the relevant claims

So now that Azure AD is ready for us, we have to configure ADFS to actually send the appropriate claims across to ‘inform’ it of what is happening or what it is doing.
The first is to make sure we send the InsideCorporateNetwork claim so Azure AD can apply the ‘bypass for all internal users’ rule.  This is well documented everywhere, but the short version is, within your Microsoft Office 365 Identity Platform relying party trust in ADFS and Add a new Issuance Transform Rule to pass through the Inside Corproate Network Claim:
MFABypass4
Fun fact:   The Inside Corporate Network claim is automatically generated by ADFS when it detects that the authentication was performed on the internal ADFS server, rather then through the external ADFS proxy (i.e. WAP).  This is why it’s a good idea to always use an ADFS proxy as opposed to simply reverse proxying your ADFS.  Without it you can’t easily tell whether it was an ‘internal’ or ‘external’ authentication request (plus its more secure).
The other important claim to send through is the authnmethodsreferences claim.  Now you may already have this if you were following some online Microsoft Technet documentation when setting up ADFS MFA.  If so, you can skip this step.
This claim is what is generated when ADFS successfully performs MFA.  So think of it as a way for ADFS to tell Azure AD that it has performed MFA for the user.
MFABypass6

Step 4: “Cutover” the MFA execution

So now that everything is prepared, the ‘cutover’ can be performed by doing the following:

  1. Disable the MFA rules on the ADFS Relying Party Trust
    Set-AdfsRelyingPartyTrust -TargetName "Microsoft Office 365 Identity Platform" -AdditionalAuthenticationRules $null
  2. Enable the Azure AD CA Policy

Now if it all goes as planned, what should happen is this:

  1. User attempts sign into an Azure AD application.  Since their domain is federated, they are redirected to ADFS to sign in.
  2. User will perform standard username/password authentication.
    • If internal, this is generally ‘SSO’ with Windows Integrated Auth (WIA).  Most importantly this user will get a ‘InsideCorporateNetwork’ = true claim
    • If external, this is generally a Forms Based credential prompt
  3. Once successfully authenticated, they will be redirected back to Azure AD with a SAML token.  Now is actually when Azure AD will assess the CA policy rules and determines whether the user requires MFA or not.
  4. If they do, Azure AD actually generates a new ADFS sign in request, this time specifically stating via the wauth parameter to use multipleauthn. This will effectively tell ADFS to execute MFA using its configured providers
  5. Once the user successfully completes MFA, they will go back to Azure AD with this new SAML token that contains a claim telling Azure AD that MFA has now been performed and subsequently lets the user through

This is what the above flow looks like in Fiddler:
MFABypass9.png
This is what your end-state SAML token should like as well:
MFABypass10
The main takeaway is that Step 4 is the new auth flow that is introduced by moving MFA evaluation into Azure AD.  Prior to this, step 2 would have simply perform both username/password authentication and MFA in the same instance rather then over two requests.

Extra Considerations when enabling MFA on All Cloud Apps

If you decide to take a ‘exclusion’ approach to MFA enforcement for Cloud Apps, be very careful with this.  In fact you’ll even see Microsoft giving you a little extra warning about this.
MFABypass12
The main difference with taking this approach compared to just doing MFA enforcement at the ADFS level is that you are now enforcing MFA on all cloud identities as well!  This may very well unintentionally break some things, particularly if you’re using ‘cloud identity’ service accounts (e.g. for provisioning scripts or the like).  One thing that will definitely break is the AADConnect account that is created for directory synchronisation.
So at a very minimum, make sure you remember to add the On-Premises Directory Synchronization Service Account(s) into the exclusion list for for your Azure AD MFA CA policy.
The very last thing to call out is that some Azure AD applications, such as the Intune Company Portal and Azure AD Powershell cmdlets, can cause a ‘double ADFS prompt’ when MFA evaluation is being done in Azure AD.   The reason for this and the fix is covered in my next article Resolving the ‘double auth’ prompt issue with Azure AD Conditional Access MFA and ADFS so make sure you check that out as well.
 

Category:
ADFS, Architecture, Azure Platform, Identity and Access Management, Security
Tags:
, , ,

Join the conversation! 9 Comments

  1. Great article, I could have used this a few months back when implementing. One thing to mention is that I believe this only applies to modern auth capable clients so older Office clients will still be reliant on existing ADFS claims rules to maintain enforcement. I ended up with a Hybrid approach of maintaining MFA claims rules for older clients at ADFS and passing anything using the OAuth endpoint through to Azure AD to be processed by conditional access.

    • Hi David,
      Thanks for the kind feedback. Yes absolutely agree – this is all hinged on Modern Auth capable clients.
      But having said that, the MFA flows today for Office clients are reliant on Modern Auth anyway but for other ‘CA’ type scenarios (such as ‘block/allow’ access based on group or network location for ‘active auth’ clients) – absolutely I can see a use case for managing a hybrid approach. Perhaps yet another article for another day 🙂
      Cheers,
      Dave.

  2. Great post. I hadn’t realised there are dual auth requests but makes sense. Haven’t read that explained anywhere else

  3. Great article David. One question I have (or at least I cannot overcome) is the ability to bypass MFA for Trusted devices. I have setup a conditional access policy and I do not get prompted for MFA on premise (I am assuming because I am on a trusted network) but I still get prompted on my domain-joined or Intune trusted devices when I am not on a trusted network. My Access control is set to “Require one of the selected controls” which I have selected Require MFA, Require compliant, or Require domain joined.
    Now the catch is that my SFBO is in hybrid mode and our Exchange is in Hybrid mode and we are using MA. As soon as I enable MFA then the users cannot use SFBO remotely. Even though we are in Hybrid Mode our users are all cloud based.

    • Hey Rob,
      Ok, in the first part of your query – it sounds like your Intune device compliance and workplace join policies are not working as expected. The first thing I’d be looking into is making sure in Azure AD (or intune) to find those device objects and making sure they are marked as ‘compliant’ or ‘domain joined’. Admittedly this part of the debugging is annoying as the tools for this are not great. For the domain joined parts, make sure you are using Windows 10 with the appropriate GPOs, or for Win8/7 you have deployed the latest version of the workplace join MSI.
      As for SFBO in hybrid with MFA – this is a tricky one. I believe this is probably due to you needing to enable Modern Auth on your on-prem environment. I supect the breakdown is occuring because as part of the SIP autodiscover process, the onprem environment is still involved somewhat, and it can’t handle the MFA prompts? (I’m guessing here as unfortunately I have limited experience in this space).
      Perhaps this technet article might be of assistance
      https://support.microsoft.com/en-au/help/3126604/skype-for-business-mobile-users-can-t-sign-in-when-modern-authenticati
      Regards,
      Dave.

  4. David – Wondering if you could help verify if a particular use-case is feasible for the solution you described. We have AAD and ADFS today, and today we protect access to both O365 and Azure using ADFS conditional access using PKI certs as the MFA means. (All our federation relying parties are done with ADFS) We would like to leverage Azure AD SaaS app federation (in this case to Atlassian apps like Confluence and Jira), but Azure AD conditional access does not support PKI certs as a method for MFA. Is it possible to still construct the federation to SaaS like Confulence using Azure AD, but have the conditional access challenge completed by ADFS using the PKI cert as the MFA means?

    • Hi Brian,

      Yes you can. What you would do is set your federated domain to ‘supportsMFA’ to true which tells AAD to send the MFA request to you ADFS server. Since I presume you already have cert based MFA configured on ADFS, the client will be asked to present the cert as part of that flow, perform that successfully and as long as your RPT for your AAD/O365 is configured to pass the strongauthenticaiton claim up, it should be all fine and dandy.

      Hope that makes sense!
      Dave.

  5. Hello David,
    Got this post while i was searching for a use case. I am still not sure if my use case is possible or not (even after reading this article…no offense). This is what i would like to achieve:
    I have Servicenow added as a relying party on ADFS (server 2016). Now, Is it possible to configure MFA on ADFS and conditional access policies on Azure AD?

  6. Hi,
    I have the same question as Vinit. We use Service-Now with standard URL https://.service-now.com with ADFS and want to restrict this URL from domain joined devices only. Azure conditional access can do that. Can you please confirm if Service-Now with on-prem ADFS can be configured to use AAD conditional access. If yes, how?

Comments are closed.