Search code examples
javascriptinternet-explorercorscross-domainaccess-control

IE CORS - Access-Control-Allow-Headers error even though headers are specified


I'm currently submitting an AJAX request on a web page to an API endpoint which works in Chrome and Firefox but not in IE.

The error message I'm getting in IE's dev tools is:

SEC7123: Request header x-custom-header was not present in the Access-Control-Allow-Headers list.
SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied.


Looking at the pre-flight OPTIONS request, here are some of the headers:

Origin: http://www.example.org
Access-Control-Request-Headers: content-type, accept, x-custom-header
Access-Control-Request-Method: GET

The response of the pre-flight shows this:

Access-Control-Allow-Headers: content-type, x-custom-header
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS
Access-Control-Allow-Origin: *


After this happens, the AJAX request isn't executed. It looks like IE cannot see that the header was returned in the response of the pre-flight request.


Any help would be greatly appreciated and if you need more information, please ask.

Thanks, James


Solution

  • Okay, so I've found the solution. It turns out that IE enforces the headers' values to be in a comma separated list and the pre-flight request was responding with multiple headers with the same key. (Even though the W3 says that doing this should be okay). For example, the response could specify the Access-Control-Allow-Headers header twice:

    Access-Control-Allow-Headers: content-type
    Access-Control-Allow-Headers: accept
    

    All of the dev tools (including IE's) on the network tab show the headers combined together as a comma separated list even though they're technically different headers with the same name. This is where the confusion came from.

    This was discovered when using Postman to simulate the pre-flight requests and seeing the headers be returned as separate items.

    Therefore, to fix this, ensure that the CORS headers such as "access-control-allow-headers" contain a comma separated list rather of the headers which are required since IE will only accept the first one sent. For example, the response should be:

    Access-Control-Allow-Headers: content-type, accept