Ajax how to get 401 Unauthorized error from Owin

I recently started working on a ASP.NET MVC project which uses Microsoft Owin Identity authentication as its authentication mode. The generated template code was working fine until an error occurred during a Http request to an authorized filtered action method from an AJAX call. AJAX will receive some misleading error due to the prevention of access to the action method due to authentication session has been expired. Ideally AJAX call should receive an unauthorized exception for this scenario.

The snippet we are interested is located in the ~/App_Start/Startup.cs class file.

Generated code from the project template as below.

public void ConfigureAuth(IAppBuilder app)
{
    // Enable the application to use a cookie to store information for the signed in user.
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        CookieName = "MySweetAuthCookie",
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/SignIn"),
        SlidingExpiration = true,
        ExpireTimeSpan = TimeSpan.FromMinutes(20)
    });
}

This way of implementation will not expose the real exception to the AJAX request and at the client end we receive some other wrapper exception instead the originally caused 401 – Unauthorized exception. We only need to add few more code lines to return exception without wrapping just for AJAX requests.

public void ConfigureAuth(IAppBuilder app)
{
    // Enable the application to use a cookie to store information for the signed in user.
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        CookieName = "MySweetAuthCookie",
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/SignIn"),
        SlidingExpiration = true,
        ExpireTimeSpan = TimeSpan.FromMinutes(20),
        Provider = new CookieAuthenticationProvider()
        {
            OnApplyRedirect = ctx =>
            {
                // apply redirect only for non-ajax requests.
                if (!IsAjaxRequest(ctx.Request))
                {
                    ctx.Response.Redirect(ctx.RedirectUri);
                }
            }
        }
    });
}
 
/// 
/// Detect current request is an AJAX request or not.
/// 

private static bool IsAjaxRequest(IOwinRequest request)
{
    // check http header parameter in request query items collection
    IReadableStringCollection query = request.Query;
    if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
    {
        return true;
    }
 
    // check http header parameter in http request header items collection
    IHeaderDictionary headers = request.Headers;
    return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
}

This code will allow the provider to detect the incoming http request is an AJAX request or not. And based on that we can allow to redirect o wrapper exception or to let it handle its own way in client side by receiving the raw exception.

Comments