ADFS: Certificate Authentication with Azure AD & Office 365

Howdy folks!

Azure AD just announced GA support for certificate authentication in this blog post! I’ve had a few folks asking me about how to configure ADFS for this. So, here are some instructions and gotchas for it.

Before we get started, do note that certificate authentication partially worked before this recent additional to Azure AD. It worked well on Windows devices (I use it with my smartcard on a regular basis against the ADFS service at our own company). The key capabilities that did not work well were:

  • Native apps on iOS & Android did not support this even with modern authentication. The challenge here was that the browser dialog that the authentication library used on these devices could not access the certificate provisioned to the device (app sandboxing) or the browser dialog did not support client TLS capabilities. This changed with the latest iOS/Android platforms and the authentication support makes full use of these capabilities.
  • EAS access to Exchange Online did not support certificate authentication and only supported HTTP basic authentication.
  • There was no way in Azure AD to revoke a prior session state when the cert (or the device that stores it) gets compromised. Note that this is very important because while ADFS may do the orignial authentication for modern auth apps, subsequent access tokens are obtained by the app from Azure AD by using a refresh token. In this interaction the request does not go back to ADFS.

Well, all of this is fixed now!

A few things to remember:

  • Support for certificate authentication on native apps requires modern authentication. The only exception is EAS for which there is special support in EXO & Azure AD.
  • Certificate authentication for browser apps & native apps is only supported for federated tenants that use ADFS or a 3rd party IDP that supports certificate authentication. [Note:  Using certificate authentication via EAS to EXO is supported for managed domains. However, if the end user were using browser or native apps, they would have to use username/password to login]
  • The Office app needs to have been updated with the latest modern authentication libraries. Not all of them support yet. Please refer to Office documentation or the Azure AD documentation for the list. For now, the list of apps is called out in the blog post.
  • Some of the Office apps (with modern authentication enabled) send 'prompt=login' to Azure AD in their request. By default Azure AD translates this in the request to ADFS to 'wauth=usernamepassworduri' (asks ADFS to do U/P auth) and 'wfresh=0' (asks ADFS to ignore SSO state and do a fresh authentication). For people interested in certificate authentication on these applications, you will need to modify the default Azure AD behavior. Just set the 'PromptLoginBehavior'  in your federated domain settings to be 'Disabled'. See /en-us/windows-server/identity/ad-fs/overview/ad-fs-faq#BKMK_7 for more information and parameter reference.

How do I configure my ADFS for this?

Yay! Now that you are all bought into certificate authentication, let’s get you going and get this configured on ADFS. You can check out the Azure AD configuration in the blog post.

Ensure pre-requisites are met & configured

  • You need ADFS 2012R2 or higher. You will need the Web Application Proxy to support this for extranet access. If you were per-chance using a third party proxy, this is not supported unless they support MS-ADFSPIP protocol document (all the MUST’s).
  • Ensure that all the roots and intermediary certificate authorities are populated correctly on all your ADFS and Web Application Proxy servers. ADFS uses the core windows OS support for this functionality and ensuring that you have the trust chain configured is needed for client TLS to work correctly. Most folks will use group policy to do this. TIP: Ensure that roots & intermediaries are placed correctly in their own stores. Having duplicates or improperly placing them will prevent it from working correctly.
  • Ensure that port 49443 is reachable between the client device and ADFS as well as the client device and WAP servers. This may require additional firewall configuration to allow this traffic to flow between the client and ADFS/WAP servers. This is the default port at ADFS performs user certificate authentication.
  • ADFS 2016 supports a mode that allows user certificate authentication to happen over port 443. This is useful when you have more stringent firewall restrictions. To enable this, you will need your SSL certificate to have certauth.your_adfs_service_name added as an alternate subject name. Also, in this mode, wild card certs with no alt subj name are not supported. To configure this, you can find more info here.
  • Ensure that all revocation endpoints are reachable from the client device (inside or outside your network) as well from each of the ADFS/WAP servers.

Enable Certificate Authentication on ADFS

  • Open up the ADFS Management Console (MMC plug-in) and enable it on the primary authentication policy for extranet and optionally the intranet. Given most of your devices that use certificate authentication are likely to come only from the extranet, you could just enable it for the extranet. The policy should look like this

ADFS-cert-auth

  • Validate that it works. You can use Windows or iOS/Android devices with a browser to check if it works correctly. After browser validation, you can try one of the supported Office apps listed in the blog post to try it out. You are now set. If you are having issues, refer to #1 to check it out.

Send the necessary claims to Azure AD.

Azure AD needs ADFS to send it the issuer and the serial # so that it can revoke or deny authentication in access scenarios for EAS or when a modern auth application attempts to exchange a refresh token for an access token. This way if a device ever gets lost or stolen, the admin can update the CRL and Azure AD will revoke access using the cert authentication.

  • First we need to get ADFS to pass these claims through to the issuance pipeline by adding the following 2 rules in the “Active Directory” Claims Provider trust. This tells ADFS that any time we are authenticating an Active Directory User, to allow this to pass through.

c:[Type == " https://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber"\]  => issue(claim = c);

c:[Type == " https://schemas.microsoft.com/2012/12/certificatecontext/field/issuer"\]  => issue(claim = c);

  • Now add the same rules in the Azure AD/Office 365 relying party trust.

c:[Type == " https://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber"\]  => issue(claim = c);

c:[Type == " https://schemas.microsoft.com/2012/12/certificatecontext/field/issuer"\]  => issue(claim = c);

Customize the Sign-In experience

By default ADFS displays "Sign in using an X.509 certificate" when using user certificate authentication. This is not very user friendly. Changing this is simple with powershell. Execute the following command to set it to what you need to be. In this case I'm choosing to keep it simple as "Sign in with a certificate".

Set-AdfsAuthenticationProviderWebContent -Name CertificateAuthentication -DisplayName "Sign in with a certificate"

It would look like this

adfs-cert-auth-user

Note: When both forms and certificate authentication is enabled, ADFS makes this a choice page to select and has a special optimization for username/password form and shows it inline. This was done as username/password case was the most common form and we optimized for this. You can choose to customize this ordering with javascript customizations. For example, let's say that you want certificate authentication only on iOS and Android devices and not for Windows PC's. You can do the following customization with JS:

  • Hide the choice entries (don't disable) when loading up.
  • Detect the platform using the user agent string that is available to JS
  • Auto-click "Cert Auth" link if iOS/Android is detected
  • Auto-click or un-hide other elements if a platform outside of iOS/Android is detected

Tip: The Authenticator application is required for Certificate Based authentication on iOS. So, to ensure that you have a good experience for your end users, you can add additional HTML to the login page to pre-install the authenticator app and add a link to the authenticator app. Also, on iOS, if certificate authentication is used in the additional authentication stage, you will see 2 prompts for the primary authentication stage. This is because, the authenticator application detects for certificate authentication based on a client TLS challenge and reinitiates the entire authentication with the system web view that has access to the user certificates provisioned. We recommend using certificate authentication in the primary stage. 

[Optional] Restrict token issuance based on certificate properties

There’s more fancy stuff you can do. In many cases, customers may have multiple types of user certificates in their environment and may want to restrict this type of access only if the user were using a certificate that was provisioned through an MDM channel or via group policy for Windows Devices. In this case you would,

  • Ensure that there was a distinct issuer or EKU for the certificate template.
  • Pass through these claims as we did in the prior section. The claim type for EKU (issuer is already handled in the prior section) would be “https://schemas.microsoft.com/2012/12/certificatecontext/extension/eku”
  • Add issuance authorization rules on the Azure AD/Office 365 relying party trust to restrict access by checking for the specific EKU or issuer if the user had done certificate authentication.

That’s it! You are all set from the ADFS side. You also want to upload the certificate authority information (and the CRL endpoints) to Azure AD as per instructions in the blog post (or in Azure AD docs)

Azure AD Blog Post announcing GA for Certificate Authentication Support Azure AD Docs for Certificate Authentication Support (Note that this takes you to the iOS instructions and there is a drop down at the top of the page for Android)

That concludes my post. If you have any questions, tweet me @MrADFS.

Thanks

//Sam (@MrADFS)

Comments

  • Anonymous
    August 07, 2016
    The comment has been removed
    • Anonymous
      August 10, 2016
      @Moshin, could you elaborate on your use case? This will help in providing you the right response.
  • Anonymous
    August 12, 2016
    Hi Sam>>Just set the ‘PromptLoginBehavior’ in your federated domain settings to be ‘Disabled‘. I can't find any reference anywhere about that parameter. Are you sure that is the parameter?Thanks.
    • Anonymous
      August 12, 2016
      Did you download the latest PSH from the link that I posted?
  • Anonymous
    September 07, 2016
    The comment has been removed
    • Anonymous
      September 13, 2016
      Are you sure that the cert was provisioned into the system keychain by Mobile Iron?
      • Anonymous
        October 11, 2016
        I have similar problem.Certificate deployed thru MobileIron, works fine for auth in office365/adfs if using Safari.Logindialog from our ADFS when trying to use onedrive does nopt show the "Log in using x.509 certificate" link.
        • Anonymous
          October 26, 2016
          The comment has been removed
  • Anonymous
    October 31, 2016
    Where is the “Active Directory” Claims Provider trust? in ADFS I only see it as an Attribute store.
    • Anonymous
      November 07, 2016
      Hi Chad, this should be under your claims providers trusts node in the MMC snap-in for ADFS.
  • Anonymous
    December 14, 2016
    We are getting 401 error when using DoD certs and EAS. What setting could we be missing?
    • Anonymous
      July 10, 2017
      Are you still using this?
  • Anonymous
    January 03, 2017
    Is ADFS MFA supported with the second factor being the certificate? I have set up as per the instructions and I can get the iOS app to select the certificate but then it just hangs? Any tips for troubleshooting this?
    • Anonymous
      July 10, 2017
      Yes, this should work. Please see my troubleshooting steps. You need the authenticator app installed for this to work.
  • Anonymous
    January 04, 2017
    Where is the best place to look for support to this? O365 or Premier? I have it setup but no client devices ever prompt for a certificate. It just times out.
    • Anonymous
      July 10, 2017
      Are you still having issues? Both O365 & premier support should work.
  • Anonymous
    February 24, 2017
    Maybe someone can help with insight on my issue. I have cert auth working on iOS for an active sync profile using intune and scep to supply the cert. However when I try with one drive or safari and use the link, it just hangs and times out?
    • Anonymous
      July 10, 2017
      Check out some of the troubleshooting notes that I had in the blog post. If not resolved, please provide more information on what the symptom looks like.
  • Anonymous
    March 02, 2017
    I posted a legitimate question about this? Not sure why it hasn't been published?I have managed to get Outlook for iOS and all browser based access to Offfice 365 to work but unfortunately the native iOS application continues to prompt for a password? Has anyone seen this behaviour the Email is present in the subject alternative?
    • Anonymous
      July 10, 2017
      Are you still seeing issues? For EAS, you will need your MDM to configure it for the cert profile.
  • Anonymous
    April 06, 2017
    What are the list of values for the attribute PromptLoginBehavior? What does it mean when its value is set to TranslateToFreshPasswordAuth?
  • Anonymous
    October 31, 2017
    Thanks for the detailed post, this has helped tremendously.I'm having some trouble with external certificate based authentication through our ADFS proxy. When logging in via the domain, I am redirected to the ADFS server for authentication, and it prompts me to select a certificate.If I access the authentication page via the extranet, it give me the X.509 sign in option, but when I click the link it never prompts for a certificate. It eventually just times out.What could be causing this?
    • Anonymous
      January 15, 2018
      Hi Nick, this is likely due to firewall between the client and the Web Application Proxy servers. By default port 49443 is required to be open on 2012R2. There is an option to use port 443 in ADFS 2016.