Azure Multi-Factor Authentication Server portal looping layer-8 issue

I’ve recently designed and implemented a large hybrid identity provider that comprises Azure Active Directory Premium, Active Directory Federation Services and Azure Multi-Factor Authentication Server.  One of the things I did was utilise Internet Information Services (IIS) URL rewrite rules to simply the user experience when interacting with the Azure MFA Server user portals.  In doing so I encountered a nasty issue far more prevalent on Chrome than IE or Firefox that I think is worth discussing.

First things first.  This is not a Chrome issue.  This is a layer-8 issue.  Ultimately my URL rewrite rules were a bit sloppy, or not tight enough.  Here’s what happened and how we fixed it.

Background

The MFA Server requires you implement a user portal and a mobile portal.  Collectively these two portals are referred to as the user portals and they’re deployed in the perimeter network or DMZ and maybe also internally.  In my case I duplicated the portals internally and externally, i.e. the URLs were available wherever you are, although through the use of split-brain DNS you would hit different load balancers.

So, we had the following portal URLs:

Internet DNS resolves mfa.customer.com to our DMZ load balancer VIP.  Corpnet DNS resolves to our internal VIP.  Users hit both the internal and external ~/user portal.  Only devices communicate with the ~/mobile portal (it’s for registering the Azure MFA app) therefore 99% of this traffic originates from the Internet with only VIP iPads having actual corpnet connectivity and using corpnet DNS.

IIS URL rewrite rules

To simplify the user experience I utilised URL rewrite rules to perform the following redirects:

http://mfa.customer.com https://mfa.customer.com/user/
https://mfa.customer.com https://mfa.customer.com/user/
http://mfa.customer.com/user https://mfa.customer.com/user/
http://mfa.customer.com/mobile https://mfa.customer.com/mobile/

In other words, if you just stick mfa.customer.com into your browser you’ll end up in the correct place.  Likewise if you actually utilise the HTTPS prefix but don’t add the subsite you’ll end up in the right place.  The mobile redirect is not really needed as the URL is baked into the web services and the device gets the full URL and will break if it hits the redirect rule, however it’s there for completeness and laziness, i.e. testing the WS is live.

The issue

Some users were reporting being unable to utilise the portal.  The specific behaviour was that they would logon to the portal, which requires MFA, and then clicking any URL, e.g. electing to Change Method or Activate Mobile App, would result in them being returned to the logon page and having to re-logon.  This looping persisted with no ability to actually do anything within the portal.

The interesting thing was that not all users were experiencing it.  And not all of us could reproduce it.  Interestingly I was affected, but only on Chrome and not using IE (my default browser), Firefox or Edge.

I checked that all the URL rewrite rules were consistent across all nodes and got the load balancing expert to recheck the persistence settings were in line with our design (client-IP persistence) and they were.

Anyway, to cut quite a long story short, the Premier case was raised and escalated and we checked and rechecked and traced and retraced the behaviour.  We had escalation engineer and developer in the mix.  Finally, a ninja named Richard Lang, identified the issue…

Root Cause

The failure to utilise the portal after a successful logon was determined to be due to the clearing of web server session variables during an extra request made to Login.aspx.  The error is far more prevalent in Chrome, however it is not believed to be a bug in Chrome, rather a different, albeit appropriate, way of handling favicon.ico requests.  (Browsers automatically generate requests for this favicon.ico to display small icons for shortcuts or bookmarks.)

During the login process, there was a request for a favicon at the root of the web application, e.g. http://hostname/favicon.ico.  In our environment/implementation, the configured URL Rewrite rules cause this request to be redirected, ultimately ending with a request to https://hostname/user/login.aspx.  This page is configured such that new sessions are started whenever you navigate to the page.  Thus, when this page is requested unexpectedly during the OTP page lifecycle, the session is cleared.  Under default/out-of-box configuration, the request to favicon.ico would not be loading login.aspx and this would not occur.  This behavior in login.aspx is by design and is not incorrect.

The difference between Chrome and other browsers (IE, Edge and Firefox were tested) is not fully understood, however it is certainly due to slightly different handling of favicon.ico requests.  It is believed that perhaps IE/FF are caching the favicon.ico failure and not sending as many retries as Chrome.

The resolution

Add an additional URL rewrite rule, before our ~/user redirect rule, to stop processing favicon.ico requests.  Here’s my new rule.

<rule name="Ignore favicon.ico" stopProcessing="true">
  <match url="^favicon.ico$" />
  <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
  <action type="None" />
</rule>

So, the web.config for the root of my web app, i.e. e:\inetpub\mfa\, contains the following URL rewrite rules:

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <clear />

        <rule name="Redirect to HTTPS" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
            <add input="{HTTPS}" pattern="^OFF$" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/" />
        </rule>

        <rule name="Ignore favicon.ico" stopProcessing="true">
          <match url="^favicon.ico$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="None" />
        </rule>

        <rule name="Redirect to ~/User" enabled="true" stopProcessing="true">
          <match url="^.*$" />
          <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
          <action type="Redirect" url="user/" />
        </rule>

      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Let me summarise those rules:

  1. Redirect to HTTPS.  As the name suggests this redirects any request to HTTP host to HTTPS
  2. Ignore favicon.ico.  As the name suggests, and indeed this post hopefully explains, we need to stop processing URL rewrite rules if the request is for favicon.ico, so this rule has no action type and simply tells the rewrite rules engine to stop
  3. Redirect to ~/user.  This is the rule that redirects anything that is not https://mfa.customer.com/user/ or https://mfa.customer.com/favicon.ico to https://mfa.customer.com/user/

Summary

The [on-premises] Azure MFA Server user portal login.aspx page clears all existing sessions, so you do not want to accidently redirect a client to this page when they have already logged on, which is exactly what I was doing until I put an additional IIS URL rewrite rule into my configuration to do nothing but stop processing requests for favicon.ico.

If you want to improve your user experience and redirect users to the subsite, ensure you correctly handle requests to favicon.ico.

Lastly, just in case you want to see what the user interface and experience looks like, here is my ignore rule:

clip_image001

Hope this helps!

Advertisements

About Paul Williams

IT consultant working for Microsoft specialising in Identity Management and Directory Services.
This entry was posted in Azure MFA and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s