Note: This question is not about AWS REST API Gateway, this question is about AWS HTTP API Gateway
My AWS HTTP API Gateway does not allow cookies to be passed.
I am using
express.js app on server hosted on ECS
Have set cors as follows:
On HTTP API Gateway:
On the express.js server I have configured cors in the following way:
In app.js
const cors = require("cors");
app.use(cors({
credentials: true
}));
The response to requests are sent in following way:
const options = {
maxAge: 900000,
httpOnly: true,
secure: true,
sameSite: 'none'
};
res.status(200)
.cookie("accessToken", accessToken, options)
.json({});
When I remove HTTP API Gateway from being in between client and server, the client is receiving cookies properly. But when calls are made to API Gateway, response is throwing following error:
**Access to fetch at 'https://api.*****.**/login' from origin 'https://cookie.*****.**' has been blocked by CORS policy: Request header field custom_field_name is not allowed by Access-Control-Allow-Headers in preflight response.**
^ How do I resolve this error?
Here is the preflight request and its response from developer console > network
GENERAL
Request URL: https://api.*****.**/login
Request Method: OPTIONS
Status Code: 204
Remote Address: [64:ff9b::306:a6f7]:443
Referrer Policy: strict-origin-when-cross-origin
RESPONSE HEADERS
access-control-allow-headers: *
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: https://cookie.*****.**
access-control-max-age: 0
apigw-requestid: CIlgSiwhBcwEJyQ=
date: Thu, 08 Jul 2021 04:45:02 GMT
REQUEST HEADERS
:authority: api.*****.**
:method: OPTIONS
:path: /login
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
access-control-request-headers: custom_field_name,content-type
access-control-request-method: POST
origin: https://cookie.*****.**
referer: https://cookie.*****.**/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html
Read point number 5 about Access-Control-Allow-Headers
That field has the list of allowed headers that you can pass through. You just need to add set-cookie to that list
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
This is different from other cors related questions
I am running my node backend-api on microservices on kubernetes deployed on Digitalocean. I have literally read all the blogs/forums related to this issue and haven't found any solution (specifically the ones related to Digitalocean).
I am unable to connect to the cluster via React application running on 'localhost:3000' or anywhere outside the kubernetes cluster.
It is giving me below error:
Access to XMLHttpRequest at 'http://cultor.dev/api/users/signin'
from origin 'http://localhost:3000' has been blocked by
CORS policy: Response to preflight request doesn't pass access
control check: Redirect is not allowed for a preflight request.
The kubernetes cluster's loadbalancer is listening on "cultor.dev" which is set as a local domain in /etc/hosts.
I am able to make it work using Postman!
NOTE:
I have tried using cors package as well, it won't help. Also, it works fine if I run this react app inside of the kubernetes cluster which I do not want.
Ingress nginx config (tried using annotations mentioned on the official website):
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
## this tells ingress to pick up the routing rules mentioned in this config
annotations:
nginx.ingress.kubernetes.io/default-backend: ingress-nginx-controller
kubernetes.io/ingress.class: nginx
## tells ingress to check for regex in the config file
nginx.ingress.kubernetes.io/use-regex: 'true'
# nginx.ingress.kubernetes.io/enable-cors: 'true'
# nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
# nginx.ingress.kubernetes.io/cors-allow-origin: "*"
# nginx.ingress.kubernetes.io/cors-max-age: 600
# certmanager.k8s.io/cluster-issuer: letsencrypt
# kubernetes.io/ingress.class: nginx
# service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"
One of the microservices config (tried cors package as well):
// APP SETTINGS
app.set('trust proxy', true);
app.use(json());
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', '*');
res.header('Access-Control-Request-Headers', '*');
if (req.method === "OPTIONS") {
res.header('Access-Control-Allow-Methods', '*');
return res.status(200).json({});
}
next();
});
Okay, after alot of research and with the help of the other answers I did the following:
I changed the request to the backend (from the client side) to https instead of http. This fixed the error Redirect is not allowed for a preflight request
I changed the config ingress nginx config to get rid of the error multiple values in Access-Control-Allow-Origin :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
nginx.ingress.kubernetes.io/default-backend: ingress-nginx-controller
kubernetes.io/ingress.class: nginx
## tells ingress to check for regex in the config file
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
add_header Access-Control-Allow-Credentials true;
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
I hope it helps others as well.
Why are the cors settings commented?
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
add_header Access-Control-Allow-Credentials true;
Same issue on GitHub
Redirect is not allowed for a preflight request.
Seems like there is a redirect happening. There isn't enough information to conclude where. My guess is that you have TLS set up on your Ingress and http://cultor.dev/api/users/signin is being automatically redirected to https.
CORS policy: Response to preflight request doesn't pass access
control check: Redirect is not allowed for a preflight request.
The preflight CORS request is actually a separate request that the browser makes to your server to check if the access control headers sent back in the response will accept the main request. The preflight request uses the HTTP OPTIONS method. I bet if you log the req.method for incoming requests you will see the OPTIONS requests coming in.
When you receive one of these preflight requests you should respond with the appropriate Access-Control-Allow-Origin and Access-Control-Allow-Headers response headers.
My API caters to requests from other origins, so I have set the following in .htaccess:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Headers "Content-Type,Accept"
Header always set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header always set Access-Control-Expose-Headers "Content-Type,Content-Length"
However, I would like for these headers to NOT show up when there is no preflight required, e.g., for GET requests, or when my own site is accessing this API.
An example:
$ curl 127.0.0.1/api/featured/ -I
HTTP/1.1 200 OK
Date: Thu, 24 Nov 2016 08:33:47 GMT
Server: Apache/2.4.18 OpenSSL/1.0.1k-fips PHP/5.6.19
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Accept
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Expose-Headers: Content-Type,Content-Length
X-Powered-By: PHP/5.6.19
Content-Type: text/html; charset=UTF-8
This feels rather extraneous; this is a curl in localhost, and it's still sending the CORS headers. How should I go about this?
Suppressing the CORS headers when the request is same-origin can be done with something like:
SetEnvIf Origin "^https://example\.com$" IS_SAME_ORIGIN
Header always set Access-Control-Allow-Origin "*" env=!IS_SAME_ORIGIN
Header always set Access-Control-Allow-Headers "Content-Type,Accept" env=!IS_SAME_ORIGIN
Header always set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS" env=!IS_SAME_ORIGIN
Header always set Access-Control-Expose-Headers "Content-Type,Content-Length" env=!IS_SAME_ORIGIN
The SetEnvIf makes Apache check the Origin request header and set an IS_SAME_ORIGIN environment variable if the value of the Origin header is "https://example.com".
The other lines use the optional final argument of the Header directive to specify that the CORS headers are sent only if the IS_SAME_ORIGIN environment variable is not set.
I get this error in my console:
XMLHttpRequest cannot load https://example.com/shop/xx/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access.
How can I fix this?
I have added this to my .htaccess:
And enabled mod_header + restarted apache.
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
I can't figure out why my .htaccess header settings doesn't work.
My .htaccess file content:
Header set Access-Control-Allow-Origin *
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "*"
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
But when I remove Header's and add them in index.php then everything works fine.
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: *");
What am i missing?
This should work:
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
Just for the record, I was running into the exact same problem and none of the answers worked.
I used a headers checker tool: http://www.webconfs.com/http-header-check.php
I was testing with my IP (http://192.0.2.1/upload) and what came back was the following:
HTTP/1.1 301 Moved Permanently =>
Date => Sat, 10 Jan 2015 04:03:35 GMT
Server => Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
Location => http://192.0.2.1/upload/
Content-Length => 380
Connection => close
Content-Type => text/html; charset=iso-8859-1
There was a redirection happening and the AJAX request does not honor/follow redirects.
It turned out to be the missing slash at the end of the domain (http://192.0.2.1/upload/)
I tested again with slash at the end and I got this below. Added a slash in the script too, and it was now working.
HTTP/1.1 200 OK =>
Date => Sat, 10 Jan 2015 04:03:53 GMT
Server => Apache/2.2.21 (Win32) mod_ssl/2.2.21 OpenSSL/1.0.0e PHP/5.3.8 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By => PHP/5.3.8
Access-Control-Allow-Origin => *
Access-Control-Allow-Methods => PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers => *
Content-Length => 1435
Connection => close
Content-Type => text/html
Use this tool to test if your headers are good and to troubleshoot what is happening.
I have a shared hosting on GoDaddy. I needed an answer to this question, too, and after searching around I found that it is possible.
I wrote an .htaccess file, put it in the same folder as my action page. Here are the contents of the .htaccess file:
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
Here is my ajax call:
$.ajax({
url: 'http://www.mydomain.com/myactionpagefolder/gbactionpage.php', //server script to process data
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: beforeSendHandler,
success: completeHandler,
error: errorHandler,
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false
});
See this article for reference:
Header set Access-Control-Allow-Origin in .htaccess doesn't work
Be careful on:
Header add Access-Control-Allow-Origin "*"
This is not judicious at all to grant access to everybody. It's preferable to allow a list of know trusted host only...
Header add Access-Control-Allow-Origin "http://aaa.example"
Header add Access-Control-Allow-Origin "http://bbb.example"
Header add Access-Control-Allow-Origin "http://ccc.example"
Regards,
I activated the Apache module headers a2enmod headers, and the issue has been solved.
Try this in the .htaccess of the external root folder
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
Be careful with doing Header add Access-Control-Allow-Origin "*" This is not judicious at all to grant access to everybody. I think you should user:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "http://example.com"
</IfModule>
I +1'd Miro's answer for the link to the header-checker site http://www.webconfs.com/http-header-check.php. It pops up an obnoxious ad every time you use it, but it is, nevertheless, very useful for verifying the presence of the Access-Control-Allow-Origin header.
I'm reading a .json file from the javascript on my web page. I found that adding the following to my .htaccess file fixed the problem when viewing my web page in IE 11 (version 11.447.14393.0):
<FilesMatch "\.(json)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>
I also added the following to /etc/httpd.conf (Apache's configuration file):
AllowOverride All
The header-checker site verified that the Access-Control-Allow-Origin header is now being sent (thanks, Miro!).
However, Firefox 50.0.2, Opera 41.0.2353.69, and Edge 38.14393.0.0 all fetch the file anyhow, even without the Access-Control-Allow-Origin header. (Note: they might be checking IP addresses, since the two domains I was using are both hosted on the same server, at the same IPv4 address.)
However, Chrome 54.0.2840.99 m (64-bit) ignores the Access-Control-Allow-Origin header and fails anyhow, erroneously reporting:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin '{mydomain}' is therefore not allowed access.
I think this has got to be some sort of "first." IE is working correctly; Chrome, Firefox, Opera and Edge are all buggy; and Chrome is the worst. Isn't that the exact opposite of the usual case?
After spending half a day with nothing working.
Using a header check service though everything was working.
The firewall at work was stripping them
try this:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Credentials true
Header set Access-Control-Allow-Origin "your domain"
Header set Access-Control-Allow-Headers "X-Requested-With"
</IfModule>
It's preferable to allow a list of know trusted host.
If anyone else is trying this, the most upvoted answer should work. However, if you are having issues it could be possible the browser has cached the REQUEST. To confirm append a query string.
To complete the most upvoted answer, I want to add the case whenever the options to the header is not add in a response request, you could add the always keyword from Apache.
In my case i needed to add the access control allow origin in the response of the redirection and not in the result of the redirection.
And a redirection is giving the 302 code status so the header wasn't filled with the correct information.
In this case I needed to add it :
Header always set Access-Control-Allow-Origin "*"
For more information you can check this thread :
Apache: difference between "Header always set" and "Header set"?