Making Ajax play with Passive ADFS 2.1 (and 2.0) – Reactive Authentication

The first post, described the issue of using ADFS and Ajax to create SSO between a WebApp and a WebAPI. This solution looks at the changing the WebAPI to return 401 if the request is not authorized and then using an iFrame to authenticate the user for subsequent calls.

The last solution, pre-authorized on the first AJAX call per page load, which adds some overhead. This was because JSONP has no means of returning status codes (this is not entirely true, you can return a 200 and then have the real response inside a payload, but that is beyond this article). This solution makes use of normal AJAX calls and 401 responses to perform authorization only when it is required.

Caveats

  • This uses normal AJAX calls, so it requires CORS to be enabled on the WebAPI server for cross-domain requests. (See this guide)
  • IE8 & 9 do not support the passing of cookies with cross domain requests and therefore this method will not work as described. However, it should be possible to pass the token in the body of the AJAX request (use POST and HTTPS to maintain security) and write a customized AuthenticationModule to read the token and provide it to the WSFederatedAuthenticationModule. (This is outside the scope of this solution however)

Solution

By default, the WSFederationAuthenticationModule redirects the user to ADFS if the user is not currently authenticated (there is no valid session cookie). This can be changed with the following code

FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed += (sender, e) =>
{
    if (Context.Request.RequestContext.HttpContext.Request.IsAjaxRequest())
    {
        e.RedirectToIdentityProvider = false;
    }
};

By adding this code to ApplicationStart, or a HttpModule, we can make the WebAPI return a HttpStatus of 401 every time authentication is required (during an AJAX request). We then handle this response in our javascript.

The following Gist shows some javascript that handles the 401 response and then uses the idea of authenticating in a iFrame from the last solution, before retrying the AJAX call. The second attempt should now have the needed session cookies to authorize and succeed.

[gist https://gist.github.com/thejuan/4e535a0c468fa47fd9cc]

9 Replies to “Making Ajax play with Passive ADFS 2.1 (and 2.0) – Reactive Authentication”

  1. I’m attempting to implement this workaround but I’m confused as to how the “webAPIHtmlPage” request gets the auth token to refresh. If in my JS i catch the 401 and then request a static html file the browser pops up username/password dialog box. What am I missing?

    1. If you are using Windows Auth with ADFS, then none of this is needed. If authentication is required, it will pop-up a challenge dialog for the user to authenticate like you have mentioned.

      1. Figured out that the browser login pop up was caused by an MVC issue related to returning a 401 code. I swapped to a 416 but I’m still not getting the adfs auth to refresh by loading a static html file in the iframe. What should I be requesting as the source?

Leave a comment