0

I am seeing 401 responses when making a CORS request via jQuery AJAX from iOS Safari/Chrome or Windows 7 Firefox clients but not when made from IE/Chrome Windows 7 Clients.

I have a ASP.NET MVC 5 application which calls a Web Api 2.2 service hosted on an IIS 8.5 sever in my enterprise domain with URLs such as

mvc.mydom.com

api.mydom.com

Both sites are setup to require windows authentication.

The MVC application makes requests to the API service using a jQuery Ajax command like so

    $.ajax({
        dataType: "json",
        url: http:'//api.mydom.com/Cars/1',
        beforeSend: function (xhr) {
            xhr.withCredentials = true;
        },
        xhrFields: {
            withCredentials: true
        },
        success: function (data) {
             //Do stuff
            });
        },
        error: function (xhr, ajaxOptions, thrownError) {
             //alert stuff
            }
     });

In my Web API Application I enable CORS support as follows:

 // configured by application start

config.EnableCors();
config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());

public class CorsPolicyFactory : ICorsPolicyProviderFactory
{
   ICorsPolicyProvider provider = new MisCorsPolicyProvider();

   public ICorsPolicyProvider GetCorsPolicyProvider(System.Net.Http.HttpRequestMessage request)
   {
       return this.provider;
   }
}

public class MisCorsPolicyProvider : ICorsPolicyProvider
{
    private CorsPolicy policy;

    public MisCorsPolicyProvider()
    {
        this.policy = new CorsPolicy
        {
            AllowAnyMethod = true,
            AllowAnyHeader = true,
            SupportsCredentials = true
        };

        this.policy.Origins.Add("http://mvc.mydom.com");
    }

    public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return Task.FromResult(this.policy);
    }
}

Wondering if it was an issue with the preflight request I came across a couple of references which suggested that IIS 8.5 required the following change to the Web Config.

replace

<system.webServer>
  <handlers>  
    <remove name="OPTIONSVerbHandler"/>
  </handlers>  
<system.webServer>

with

<system.webServer>
  <handlers>  
    <remove name="OPTIONS"/>
  </handlers>  
<system.webServer>

which didn't help anything.

Looking at the requests in the developer tools both on iOS and Firefox Windows I don't see the credential being passed but I do in windows IE/Chrome.

Examples of the bad header/response are as follows:

GET http://api.mydom.com/Cars/1 HTTP/1.1
Host: api.mydom.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://mvc.mydom.com/Home/Index
Origin: http://mvc.mydom.com
Connection: keep-alive

RESPONSE

HTTP/1.1 401 Unauthorized
Content-Type: text/html
Server: Microsoft-IIS/8.5
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
Date: Wed, 17 Sep 2014 14:25:49 GMT
Content-Length: 1293
Proxy-Support: Session-Based-Authentication

On windows IE/Chrome network profiling I see a 401 error quickly followed by 200 response to the desired resource(s). This doesn't happen on iOS or win Firefox leading me to believe it's might be something to do with preflight request failing however the requests are GET's not OPTIONS. I assumed preflight requests are OPTIONS

Struggling to see what I am missing any ideas?

UPDATE

Ok I think it might because Firefox and I presume Safari and iOS correctly implement the W3C specification which states that preflight requests should not pass user credentials; as IIS is set up to require windows authentication the request fails with a 401.2 error. IE, chrome seem to carry on and authenticate hence the success. So I suppose is there a way I can turn off windows authentication for OPTIONS requests only?

MPD
  • 605
  • 1
  • 9
  • 17
  • possible duplicate of [401 response for CORS request in IIS with Windows Auth enabled](http://stackoverflow.com/questions/10723088/401-response-for-cors-request-in-iis-with-windows-auth-enabled) – Lex Li Jan 11 '15 at 12:21

1 Answers1

0

Just noticed that many guys have experienced the 401 errors when their Web API is protected by Windows authentication or such. CORS preflight requests do not contain credentials, so IIS will respond with 401.2 even before ASP.NET touches them.

A dirty workaround is to write a HTTP module and hook to IIS pipeline, which registers on HttpApplication.BeginRequest event where this module returns the expected 200 response for preflight requests.

This workaround only applies to IIS 7+ integrated mode.

You can read my blog post which contains more details.

Lex Li
  • 60,503
  • 9
  • 116
  • 147