Request header field Access-Control-Allow-Headers is not allowed by itself in preflight response
Asked Answered
M

27

440

I have come across CORS issues multiple times and can usually fix it but I want to really understand by seeing this from a MEAN stack paradigm.

Before I simply added middleware in my express server to catch these things, but it looks like there is some kind of pre-hook that is erroring out my requests.

Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response

I assumed that I could do this:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","*")
})

or the equivalent but this doesn't seem to fix it. I also of course tried

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","Access-Control-Allow-Headers")
})

Still no luck.

Mitrewort answered 10/9, 2015 at 11:1 Comment(0)
N
395

When you start playing around with custom request headers you will get a CORS preflight. This is a request that uses the HTTP OPTIONS verb and includes several headers, one of which being Access-Control-Request-Headers listing the headers the client wants to include in the request.

You need to reply to that CORS preflight with the appropriate CORS headers to make this work. One of which is indeed Access-Control-Allow-Headers. That header needs to contain the same values the Access-Control-Request-Headers header contained (or more).

https://fetch.spec.whatwg.org/#http-cors-protocol explains this setup in more detail.

Narcolepsy answered 10/9, 2015 at 12:2 Comment(12)
If you using Chrome and your not sure what headers are being requested, use the Developer Console, Network select the call being made and you can view what headers are being requested by Access-Control-Request-HeadersRevive
The Developer Console option is a good one. You can also find what you need by getting access to the request object on the server and dumping the values for the headers, but specifically the header value for "Access-Control-Request-Headers". Then, copy/paste this into your response.setHeader("Access-Control-Allow-Headers", "{paste here}")Seisin
example please!Barabbas
@Barabbas an example of this for me was header("Access-Control-Allow-Headers: Content-Type")Hoskinson
@LionelMorrison, use of chrome dev tools for matching headers. well explained !!!Undercast
I'd read a lot of "explanations" until I found yours!! everybody suggest using Access-Control-Allow-Methods but it's header('Access-Control-Allow-Headers: POST, GET, PUT, DELETE, OPTIONS, HEAD, authorization'); what did the trick for me!Gourami
Well, you need -Methods for HTTP methods, such as POST and PUT, and -Headers for HTTP headers, such as Authorization...Narcolepsy
I understand the answer, but I don't understand why we need to explicitely allow a client to send headers to a server... I guess it's a security measure, but I don't get the purpose of this. If a server doesn't handle unexpected headers, it just won't use those. If anyone can edit to explain the purpose of this "limitation", that'd be even better!Fania
If all servers were written in the way you suggest, that'd be true, but that's not the case.Narcolepsy
Checking the actual request headers using Chrome console was amazing advice! I think the big thing is that if you're working with unusual environments like Node+React microservice front end with AWS lambda backend, there are additional AMZ headers!Highjack
Another method for checking Request Headers (And Network, Response Headers, Response Body) is by using Postman's app console. Everything is there.Bliss
Get Postman desktop app, and at the bottom of the app you'll see the console icon. https://mcmap.net/q/81801/-postman-how-to-see-request-with-headers-and-body-data-with-variables-substitutedBliss
M
205

This is what you need to add to make it work.

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

The browser sends a preflight request (with method type OPTIONS) to check if the service hosted on the server is allowed to be accessed from the browser on a different domain. In response to the preflight request if you inject above headers the browser understands that it is ok to make further calls and i will get a valid response to my actual GET/POST call. you can constraint the domain to which access is granted by using Access-Control-Allow-Origin", "localhost, xvz.com" instead of * . ( * will grant access to all domains)

Mixie answered 14/5, 2016 at 15:14 Comment(7)
You cannot combine * for ...-Origin and true for ...-Credentials. It will not fail for non-credentialed requests, but it will not work for credentialed requests either. See the link I posted in my answer.Narcolepsy
Thanks Manish Arora, I used your solution in my api and it worked. HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT"); HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"); HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "localhost:4200");Incomprehension
This is saying server side all this response header munging is necessary because of "preflight"? Why? Especially for perfectly standard headers? Having used HTTP for a while it is news to me that so much boilerplate is needed.Hawsehole
@manish I had a different set of values for Access-Control-Allow-Headers that didn't work. Your set of values did. Thanks for saving time and frustration.Bin
Is there a way to wildcard some headers? Is it a bad idea to wildcard all headers? Such as response.setHeader("Access-Control-Allow-Headers", "*")? What's the security implication of doing this?Fania
I had the wildcard set and that didn't work. For the above solution to work, I had to add "Authorization" to the list. Now it's good.Valleau
@SamanthaAtkins Because the origins of the client and the server are different. You can't just let a website request some random server for security reasons.Liaotung
P
135

This problem solved with

 "Origin, X-Requested-With, Content-Type, Accept, Authorization"

Particular in my project (express.js/nodejs)

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  next();
});

Update:

Every time error: Access-Control-Allow-Headers is not allowed by itself in preflight response error you can see what wrong with chrome developer tool:
enter image description here

above error is missing Content-Type so add string Content-Type to Access-Control-Allow-Headers

Pavlodar answered 8/7, 2016 at 5:2 Comment(6)
This won't work for everyone. The value for Access-Control-Request-Headers may vary based upon environment. Get access to the request object on the server and dump the values for the "Access-Control-Request-Headers" header. Then, copy/paste this into your response.setHeader("Access-Control-Allow-Headers", "{paste here}")Seisin
Also make sure you're spelling Authorization the american way not the Britsh way. That's half an hour of my life I won't get back. Thx USA! [sigh]Nuremberg
Worked for me, sinced I used Authorization in my request headers, thanks !Chronograph
This is wht i have been looking for a long timeAtive
Because Origin is a request header that only the browser (not the client) can set, you never need to list that name in the Access-Control-Allow-Headers response header.Pentylenetetrazol
this line was the most helpful line: res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); I was scoring SO for a solution.Bibliographer
D
22

The accepted answer is ok, but I had difficulties to understand it. So here is a simple example to clarify it.

In my ajax request I had a standard Authorization header.

$$(document).on('ajaxStart', function(e){
var auth_token = localStorage.getItem(SB_TOKEN_MOBILE);
if( auth_token ) {
    var xhr = e.detail.xhr;

    xhr.setRequestHeader('**Authorization**', 'Bearer ' + auth_token);
}

This code produces the error in the question. What I had to do in my nodejs server was to add Authorization in allowed headers:

res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,**Authorization**');
Dimitri answered 9/9, 2016 at 20:35 Comment(0)
G
15

Just to add that you can put those headers also to Webpack config file. I needed them as in my case as I was running webpack dev server.

devServer: {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT",
      "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
    }
},
Guacharo answered 21/2, 2017 at 14:8 Comment(0)
I
13

To add to the other answers. I had the same problem and this is the code i used in my express server to allow REST calls:

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'URLs to trust of allow');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  if ('OPTIONS' == req.method) {
  res.sendStatus(200);
  } else {
    next();
  }
});

What this code basically does is intercepts all the requests and adds the CORS headers, then continue with my normal routes. When there is a OPTIONS request it responds only with the CORS headers.

EDIT: I was using this fix for two separate nodejs express servers on the same machine. In the end I fixed the problem with a simple proxy server.

Interknit answered 13/7, 2016 at 8:1 Comment(3)
Thanks! Can you elaborate on how you used a simple proxy server?Wynne
@Wynne "a simple proxy server" could look like this in express: /* Luke Kroon's Code Here */ app.post('/', async (req, res) => { const { url, options } = req.body; try { await fetch(url, options || undefined); return res.sendStatus(200); } catch { return res.sendStatus(400); } });Storekeeper
and then in your front-end, replace "fetch" with this function: async function proxyFetch(url, options = undefined) { const res = await fetch(localHost, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ url, options }), }); return res.status; }Storekeeper
P
7

res.setHeader('Access-Control-Allow-Headers', '*');

Pandemic answered 2/7, 2018 at 7:48 Comment(0)
G
5

I just ran into this issue myself, in the context of ASP.NET make sure your Web.config looks like this:

  <system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler"/>-->
  <remove name="TRACEVerbHandler" />
  <!--
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  -->
</handlers>

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

Notice the Authorization value for the Access-Control-Allow-Headers key. I was missing the Authorization value, this config solves my issue.

Ginsburg answered 8/3, 2017 at 3:33 Comment(0)
W
5

In Chrome:

Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.

For me, this error was triggered by a trailing space in the URL of this call.

jQuery.getJSON( url, function( response, status, xhr ) {
   ...
}
Whyalla answered 14/3, 2017 at 14:12 Comment(0)
N
5

Very good i used this on a silex project

$app->after(function (Request $request, Response $response) {
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set("Access-Control-Allow-Credentials", "true");
        $response->headers->set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        $response->headers->set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    });
Newsworthy answered 20/6, 2017 at 8:56 Comment(1)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Tael
V
5

this problem occurs when we make custom header for request.This request that uses the HTTP OPTIONS and includes several headers.

The required header for this request is Access-Control-Request-Headers , which should be part of response header and should allow request from all the origin. Sometimes it needs Content-Type as well in header of response. So your response header should be like that -

response.header("Access-Control-Allow-Origin", "*"); // allow request from all origin
response.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization");
Varner answered 18/6, 2018 at 7:59 Comment(0)
D
5

I received the error the OP stated using Django, React, and the django-cors-headers lib. To fix it with this stack, do the following:

In settings.py add the below per the official documentation.

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)
Donar answered 28/9, 2018 at 15:46 Comment(1)
exactly what I needed !!!Aksel
B
5

After spending almost a day, I just found out that adding the below two codes solved my issue.

Add this in the Global.asax

protected void Application_BeginRequest()
{
  if (Request.HttpMethod == "OPTIONS")
  {
    Response.StatusCode = (int)System.Net.HttpStatusCode.OK;             
    Response.End();
  }
}

and in the web config add the below

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />        
    <add name="Access-Control-Allow-Methods" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
  </customHeaders>
</httpProtocol>
Byron answered 25/10, 2018 at 19:27 Comment(0)
C
3

If you are trying to add a custom header on the request headers, you have to let the server know that specific header is allowed to take place. The place to do that is in the class that filters the requests. In the example shown below, the custom header name is "type":

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin",  request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, type ");
        response.setHeader("Access-Control-Expose-Headers","Authorization");
    }
}
Cristoforo answered 17/12, 2019 at 20:12 Comment(0)
U
3

add this headers into your ajax or js function

headers: {
            "Cache-Control": null,
            "X-Requested-With": null,
        }
Unship answered 25/5, 2021 at 12:35 Comment(0)
C
2

Message is clear that 'Authorization' is not allowed in API. Set
Access-Control-Allow-Headers: "Content-Type, Authorization"

Constrain answered 22/10, 2018 at 10:5 Comment(0)
Y
2

I too faced the same problem in Angular 6. I solved the issue by using below code. Add the code in component.ts file.

import { HttpHeaders } from '@angular/common/http';

headers;

constructor() {
    this.headers = new HttpHeaders();
    this.headers.append('Access-Control-Allow-Headers', 'Authorization');
}

getData() {
    this.http.get(url,this.headers). subscribe (res => {
    // your code here...
})}
Yah answered 25/10, 2018 at 5:40 Comment(0)
A
2

In Post API call we are sending data in request body. So if we will send data by adding any extra header to an API call. Then first OPTIONS API call will happen and then post call will happen. Therefore, you have to handle OPTION API call first.

You can handle the issue by writing a filter and inside that you have to check for option call API call and return a 200 OK status. Below is the sample code:

package com.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Response;

public class CustomFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
        if (httpRequest.getMethod().equalsIgnoreCase("OPTIONS")) {
            response.setStatus(Response.SC_OK);
        }
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
        // TODO
    }

    public void destroy() {
        // Todo
    }

}
Anisometropia answered 14/7, 2019 at 15:39 Comment(0)
A
2

If you're configuring an AWS API Gateway (for example, that's sending the request from a React AWS Amplify app), the solution is to append the string

Access-Control-Allow-Methods,Access-Control-Allow-Headers,Access-Control-Allow-Origin

to the Access-Control-Allow-Headers field in the Enable CORS dialog fpr the given endpoint & method:

API Gateway Enable Cors

...and then deploy the API:

enter image description here

Algeciras answered 16/9, 2022 at 1:42 Comment(0)
P
1
const express = require('express')
const cors = require('cors')
const app = express()

app.get('/with-cors', cors(), (req, res, next) => {
  res.json({ msg: 'WHOAH with CORS it works! 🔝 🎉' })
})

Adding cors in get function Is what worked for me

Pinchbeck answered 1/6, 2020 at 23:49 Comment(0)
R
1

I faced similar issues when trying to connect to a Django backend:

Request header field authorisation is not allowed by Access-Control-Allow-Headers in preflight response

After hours of searching, I finally resolved it with the help of the following comment:

Also make sure you're spelling Authorization the american way not the Britsh way. That's half an hour of my life I won't get back. Thx USA! [sigh]

So a hint for someone else who is stuck: check that you are spelling the word "Authorization" correctly. If you set the Access-Control-Allow-Headers = ["Authorisation"], you are allowing the wrong header!

Rahman answered 18/9, 2021 at 17:14 Comment(0)
T
1

We can use the following:

Access-Control-Allow-Origin, which specifies which websites should be given permission for CORS where * is for all the websites.

Access-Control-Allow-Methods, which specifies which methods should be allowed.

Access-Control-Allow-Headers, which is used for authorization.

An example of them all implemented:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
    
app.use(bodyParser.json());
app.use((req,res,next) => {
  res.setHeader('Access-Control-Allow-Origin','*');
  res.setHeader('Access-Control-Allow-Methods','OPTIONS, GET, POST, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers','Content-Type,Authorization');
  next();
});
Tuchman answered 13/2, 2023 at 7:19 Comment(1)
For some reason this doesnt work in.Net 6. I get the error Delegate 'Func<HttpContext, Func<Task>, Task>' does not take 3 argumentsErstwhile
T
0

That same issue i was facing.

I did a simple change.

  <modulename>.config(function($httpProvider){
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Therianthropic answered 5/7, 2017 at 9:4 Comment(0)
F
0

Yes, Use this i was also facing issue while integrating in angular application.

Write this.

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin,X-Requested-With, Content-Type, Accept, Authorization"
  );
  res.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,PUT,DELETE,OPTIONS");
  next();
});

Follow me Thanks

Fluorene answered 13/3, 2022 at 12:55 Comment(0)
H
0

In Next js My Problem got Solved using

const cors=micro_cors({
   origin:"https://studio.apollographql.com",
   allowMethods:['POST','GET','PUT','PATCH','DELETE','OPTIONS'],
   allowCredentials:true,
   allowHeaders:['X-Requested-With','X-HTTP-Method-Override','Content-Type','Authorization','Accept','Access-Control-Allow-Credentials','Access-Control-Allow-Origin' ]
})

then wapping it in

 export default cors(async function handler(req, res) {
   await serverStart
   if(req.method==="OPTIONS"){
    res.end()
     return false
   }
     apolloserver.createHandler({path:"/api/graphql"})(req,res)

 })
Hyperaemia answered 27/10, 2022 at 5:14 Comment(0)
T
-1

Make sure all headers you require from client is passed to to Access-Control-Allow-Headers, else you'll keep running into CORS issues. In this case, that would be 'x-api-key' else you keep running into cors issues

const options = {
  method: "GET",
  headers: new Headers({
    "X-API-Key": "ds67GHjkshjh00ZZhhsskhjgasHJHJHJ&87",
  }),
};

response.setHeader(
    "Access-Control-Allow-Headers", 
    "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, x-api-key");
Terrigenous answered 27/3, 2022 at 0:53 Comment(0)
M
-2

I just added response.headers; after

http.Response response = await http.get(
        Uri.parse(
          api + "api/users/all",
        ),
      );

The CORS setup in the backend(Django) as official documentation, Djnago-cors-headers

Mongoose answered 19/5, 2022 at 13:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.