Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing token 'access-control-allow-headers' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel

Tags:

I have two VS projects : one exposing MVC5 controllers, the other being an angular client. I want the angular client to be able to query the controllers. I read numerous threads and tried the following :

  • I added this in the server's web config:

    <system.webServer>     <httpProtocol>        <customHeaders>             <clear />             <add name="Access-Control-Allow-Origin" value="*" />         </customHeaders>     </httpProtocol> <system.webServer> 
  • I created and used the the following filter on the controller's action:

    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute {     public override void OnActionExecuting(ActionExecutingContext filterContext)     {         filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");         base.OnActionExecuting(filterContext);     } } 
  • In the angular client, I created the following interceptor :

    app.factory("CORSInterceptor", [     function()     {         return {             request: function(config)             {                  config.headers["Access-Control-Allow-Origin"] = "*";                  config.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";                  config.headers["Access-Control-Allow-Headers"] = "Content-Type";                  config.headers["Access-Control-Request-Headers"] = "X-Requested-With, accept, content-type";                  return config;             }      }; } ]);  app.config(["$httpProvider", function ($httpProvider) {     $httpProvider.interceptors.push("CORSInterceptor"); }]); 

According to Firebug, this results in the following request :

OPTIONS //Login/Connect HTTP/1.1 Host: localhost:49815 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: http://localhost:50739 Access-Control-Request-Method: POST Access-Control-Request-Headers: access-control-allow-headers,access-control-allow-origin,content-type Connection: keep-alive Pragma: no-cache Cache-Control: no-cache 

And the following response :

HTTP/1.1 200 OK Allow: OPTIONS, TRACE, GET, HEAD, POST Server: Microsoft-IIS/10.0 Public: OPTIONS, TRACE, GET, HEAD, POST X-SourceFiles: =?UTF-8?B?RDpcVEZTXElVV2ViXEdhcE5ldFNlcnZlclxBU1BTZXJ2aWNlc1xMb2dpblxDb25uZWN0?= Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: * Access-Control-Request-Headers: X-Requested-With, accept, content-type Date: Tue, 01 Sep 2015 13:05:23 GMT Content-Length: 0 

And still, Firefox blocks the request with the following message :

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:49815//Login/Connect. (Reason: missing token 'access-control-allow-headers' in CORS header 'Access-Control-Allow-Headers' from CORS preflight channel). 
like image 596
Yugo Amaryl Avatar asked Sep 01 '15 13:09

Yugo Amaryl


People also ask

What is allowed origin in CORS?

Access-Control-Allow-Origin is a CORS header. CORS, or Cross Origin Resource Sharing, is a mechanism for browsers to let a site running at origin A to request resources from origin B. Origin is not just the hostname, but a combination of port, hostname and scheme, such as - http://mysite.example.com:8080/

What is Access-Control allow credentials header?

The HTTP Access-Control-Allow-Credentials is a Response header. The Access-Control-Allow-Credentials header is used to tell the browsers to expose the response to front-end JavaScript code when the request's credentials mode Request. credentials is “include”.


2 Answers

Oftentimes, the threads that I read were suggesting several unecessary configuration steps, which created confusion. It's actually very simple...

For the simple purpose of sending a cross site request, from an angular client, to an ASP controller :

  • No angular interceptors are required.
  • No custom filters on the server side are required.
  • The only mandatory modification is to add this in the server's web.config

    <system.webServer>       <httpProtocol>           <customHeaders>               <clear />               <add name="Access-Control-Allow-Origin" value="*" />               <add name="Access-Control-Allow-Headers" value="Content-Type"/>           </customHeaders>      </httpProtocol> </system.webServer> 
like image 183
Yugo Amaryl Avatar answered Oct 11 '22 12:10

Yugo Amaryl


The problem is, some browsers don’t yet allow the * wildcard for Access-Control-Allow-Headers. Specifically, Firefox 69 and earlier doesn’t. See https://bugzilla.mozilla.org/show_bug.cgi?id=1309358.

So to ensure you get correct behavior in all browsers, the Access-Control-Allow-Headers value you send back should explicitly list all the header names you actually need to access from your frontend code; e.g., in the case in the question: Access-Control-Allow-Headers: Content-Type.

A way you can make that happen without needing to hardcode all the header names is: Have your server-side code take the value of the Access-Control-Request-Headers request header the browser sends, and just echo that into the value of the Access-Control-Allow-Headers response header your server sends back.

Or else use some existing library to CORS-enable your server. Echoing the Access-Control-Request-Headers request-header value into the Access-Control-Allow-Headers response-header value is something most CORS libraries will typically do for you.

like image 31
sideshowbarker Avatar answered Oct 11 '22 14:10

sideshowbarker