Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS hijacks CORS Preflight OPTIONS request

I am making a CORS POST request and setting the Content-Type header to json. This triggers a Preflight OPTIONS request to fire (this is good and expected)

This OPTIONS request is responded to with a 200 OK but this isn't coming from my WebAPI application.

I have a custom Message Handler in place and it never get's hit so the request is getting responded to by IIS prior to hitting ASP.NET it seems.

I have found several posts on the subject and they say the following

  1. Make sure WebDav is uninstalled / removed / disabled - DONE

  2. Make sure the OPTIONSVerbHandler is removed / changed to use aspnet_isapi.dll - TRIED BOTH

  3. Make sure the extensionlessURLHandler includes the OPTIONS verb - DONE

However, my options request is still getting hijacked. By that I mean, IIS responds with at 200 OK but isn't including an Access-Control-Allow-Origin header in the response. It isn't including this header because it is never getting to my WebAPI CORS code that would set this header.

The two best posts I could find that sound like my issue are

here: JQuery stuck at CORS preflight and IIS ghost response

and here: http://brockallen.com/2012/10/18/cors-iis-and-webdav/

I have tried turning on Failed Request tracing (FERB) in IIS and set it to trace all 200 status codes. I don't ever see the options request being logged... Not sure if this means FERB doesn't track OPTIONS requests or if I need to change something in the FERB settings to make it track OPTIONS requests, Or if this is a clue to what my problem is?

This is ASP.NET WebAPI 2.0 running on IIS 7.5 (Also tested on IIS 8 and IISExpress with same results) Doesn't matter what browser (Chrome, FF, and IE all fail the same way)

I have tried everything I can find on the subject and still can't fix my problem.

Help me StackOverflow, you're my only hope.

like image 478
Brad Cunningham Avatar asked Mar 19 '14 02:03

Brad Cunningham


People also ask

How do you handle CORS preflight request?

Your preflight response needs to acknowledge these headers in order for the actual request to work. Pay special attention to the Access-Control-Allow-Headers response header. The value of this header should be the same headers in the Access-Control-Request-Headers request header, and it can not be '*'.

How do I identify CORS preflight request?

Check for the existence of these essential information present in a preflight request: The request's HTTP method is OPTIONS. It has an Origin header. It has an Access-Control-Request-Method header, indicating what's the actual method it's trying to use to consume your service/resource.

What triggers a CORS preflight?

A CORS preflight OPTIONS request can be triggered just by adding a Content-Type header to a request — if the value's anything except application/x-www-form-urlencoded , text/plain , or multipart/form-data .

What is preflight response?

A preflight request is a small request that is sent by the browser before the actual request. It contains information like which HTTP method is used, as well as if any custom HTTP headers are present. The preflight gives the server a chance to examine what the actual request will look like before it's made.


1 Answers

A couple of things you can try here, all web.config related, firstly modify your modules element to include the attribute runAllManagedModulesForAllRequests="true", as below:

<modules runAllManagedModulesForAllRequests="true">     <remove name="WebDavModule" /> </modules> 

Then set your handlers to the below:

<handlers>    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />    <remove name="WebDav" />    <remove name="OPTIONSVerbHandler" />    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> 

This should do the trick, but if it doesn't, as a last resort you can force IIS to output the correct headers with the below:

  <system.webServer>     <httpProtocol>       <customHeaders>         <add name="Access-Control-Allow-Origin" value="*" />         <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />         <add name="Access-Control-Allow-Headers" value="Content-Type" />       </customHeaders>     </httpProtocol>   </system.webServer> 

Be wary of the wildcard value, you should really set this to the domain name that your site will be hosted on.

like image 133
Tom Hall Avatar answered Sep 22 '22 15:09

Tom Hall