NGINX Reverse Proxy and Access-Control-Allow-Origin issue - nginx

I'm configuring an NGINX Reverse Proxy.
On the browser I go to:
client url: https://www.hollywood.com
Then the web page above needs to do requests to:
server url: https://server.hollywood.com/api/auth/login
This is the configuration corresponding to: server.hollywood.com:
server {
listen 443 ssl;
server_name server.hollywood.com;
# add_header 'Access-Control-Allow-Origin' "https://www.hollywood.com" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
ssl_certificate ../ssl/lets-encrypt/hollywood.com.crt;
ssl_certificate_key ../ssl/lets-encrypt/hollywood.com.key;
location /
{
proxy_pass http://localhost:9201;
include "../proxy_params.conf";
}
}
Experiment 1:
With the Access-Control-Allow-Origin line commented out, when I access to:
client url: https://www.hollywood.com
I get the following error on the browser console (Chrome in my case):
POST https://server.hollywood.com/api/auth/login/local 502 (Bad Gateway)
(index):1 Failed to load https://server.hollywood.com/api/auth/login/local: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.hollywood.com' is therefore not allowed access. The response had HTTP status code 502.
Experiment 2:
If I enable the Access-Control-Allow-Origin line above, then I get on the browser terminal:
Failed to load https://server.hollywood.com/api/auth/login/local: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values '*, https://www.hollywood.com', but only one is allowed. Origin 'https://www.hollywood.com' is therefore not allowed access.
I don't know why multiple when before that header was not present???
Experiment 3:
In the other hand, if I go directly on the browser to the:
server url: https://server.hollywood.com/api/auth/login
with the Access-Control-Allow-Origin line commented out, I get the following (on the Network section):
Response Headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 139
Content-Security-Policy: default-src 'self'
Content-Type: text/html; charset=utf-8
Date: Sat, 09 Jun 2018 06:34:00 GMT
Server: nginx/1.13.12
X-Content-Type-Options: nosniff
Before I got: "No 'Access-Control-Allow-Origin' header is present on the requested resource." but now I see above that field is in there on the Response Headers.
Experiment 4:
If I enable again the Access-Control-Allow-Origin line above, then I get the following (on the Network section):
Response Headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: https://www.hollywood.com
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 139
Content-Security-Policy: default-src 'self'
Content-Type: text/html; charset=utf-8
Date: Sat, 09 Jun 2018 06:34:58 GMT
Server: nginx/1.13.12
X-Content-Type-Options: nosniff
Now I get two times the field: Access-Control-Allow-Origin.
Do you have any idea why my first 2 experiments are failing getting the errors relative to: Access-Control-Allow-Origin?
Thanks!

It could be that the server behind your proxy_pass was setting the Access-Control-Allow-Origin header as well.
For what it's worth for future readers with a similar problem, I found that my node.js server was passing an Access-Control-Allow-Origin: '*' header for some reason, as well as the actual header I'd set in node.js to restrict CORS. When commenting out my node.js cors middleware, the Access-Control-Allow-Origin: '*' header still remained.
To resolve this, I used the nginx proxy_hide_header directive to remove the header coming from node.js and manually adding it as it should be:
# proxying the
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# local node.js server
upstream websocket {
server 127.0.0.1:3000;
}
server {
server_name ...;
# ...;
# add the header here
add_header Access-Control-Allow-Origin https://www.hollywood.com;
# Websockets config
location /socket.io/ {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# do not pass the CORS header from the response of the proxied server to the
# client
proxy_hide_header 'Access-Control-Allow-Origin';
proxy_pass http://websocket;
proxy_http_version 1.1;
}
location / {
# ...
try_files $uri /index.html;
}
}
Googling this issue was pretty hard since most people are trying to fix CORS by making the Access-Control wide open! Here was another issue with similar problems:
https://serverfault.com/questions/751678/how-can-i-replace-access-control-allow-origin-header-in-proxy-response-with-ngin

Try this configuration:
server {
listen 443 ssl;
server_name server.hollywood.com;
ssl_certificate ../ssl/lets-encrypt/hollywood.com.crt;
ssl_certificate_key ../ssl/lets-encrypt/hollywood.com.key;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
proxy_pass http://localhost:9201;
include "../proxy_params.conf";
}
if ($request_method = 'GET') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
proxy_pass http://localhost:9201;
include "../proxy_params.conf";
}
}
}
Code based on https://enable-cors.org/server_nginx.html
Hope it helps.

Related

How do I set Access-Control-Allow-Origin on upstream errors in nginx? [duplicate]

This question already has answers here:
CORS and non 200 statusCode
(2 answers)
Closed last year.
I know there are a million answers to "how to set Access-Control-Allow-Origin in nginx" but unfortunately if there's an answer to my specific question, it's buried with all the basic answers.
I have an Angular app pointing to an nginx server with a rest service upstream - all running on my local laptop inside a docker compose.
The nginx service is configured fairly simply:
upstream REST {
# rest-service is mapped by docker-compose to the correct container
server rest-service:8080;
}
server {
listen 80;
listen [::]:80;
# This is mapped in /etc/hosts on my laptop
server_name rest-api.mylocal.com;
location / {
proxy_hide_header 'Access-Control-Allow-Origin';
# web-ui is also mapped in /etc/hosts on my laptop
add_header "Access-Control-Allow-Origin" "http://web-ui.mylocal.com";
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Max-Age' 1728000; # 20 days
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
add_header Reverse-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://REST;
}
}
If I call a valid URL on the rest service, e.g. http://rest-api.mylocal.com/api/v1/auth/config (this is an unauthenticated endpoint), everything works as expected:
curl -v 'http://rest-api.mylocal.com/api/v1/auth/config'
...
< Access-Control-Allow-Origin: http://web-ui.mylocal.com
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Max-Age: 1728000
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Content-Type, Authorization
< Reverse-Proxy: true
<
* Connection #0 to host rest-api.mylocal.com left intact
{"status":"OK","name":"foo",...}* Closing connection 0
However, if I call an invalid URL, say http://rest-api.mylocal.com/api/v1/accounts (which is an authenticated endpoint, and I provide no credentials), I get back the expected error, but there are no CORS headers. In a browser this causes everything to flake out so I don't even get the error message in Angular to display to the user:
curl -v 'http://rest-api.mylocal.com/api/v1/accounts'
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to rest-api.mylocal.com (127.0.0.1) port 80 (#0)
> GET /api/v1/accounts HTTP/1.1
> Host: rest-api.mylocal.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 403
< Server: nginx/1.21.6
< Date: Wed, 09 Feb 2022 20:57:49 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: JSESSIONID=F3B21A55841C8E5A6F838F2427A0E22B; Path=/; HttpOnly
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
<
* Connection #0 to host rest-api.mylocal.com left intact
{"timestamp":"2022-02-09T20:57:49.526+00:00","status":403,"error":"Forbidden","message":"Access Denied","path":"/api/v1/accounts"}* Closing connection 0
Browser console:
Access to XMLHttpRequest at 'http://rest-api.mylocal.com/api/v1/accounts' from origin 'http://web-ui.mylocal.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
So... Is there a way to make sure the CORS headers are still added to the response by nginx even if the response from the upstream server is an error (401/403/404/etc)?
You need to add always to each header you want added to error responses. It was added in 1.7.5: https://nginx.org/r/add_header

Nginx Cache request blocked by CORS policy when Origin is down

My cache is working fine as long as the Origin Server is running. I use "proxy_cache_use_stale" as seen below. Tried it with different Error Codes and with Updating but it won't show the cached files (They are in the cache folder). I also tried the various CORS solutions that I found but that doesn't work either.
My .conf file:
proxy_cache_path /etc/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=300d use_temp_path=off;
server {
listen 80;
listen [::]:80;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' "Origin, X-Requested-With, Content-Type, Accept" always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_cache my_cache;
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 http_403 http_404 http_429;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_key $host$request_uri|$request_body;
proxy_cache_valid 200 302 301 800d;
proxy_ignore_headers Cache-Control;
proxy_cache_methods GET HEAD POST;
proxy_pass example.com;
add_header X-Cache-Status $upstream_cache_status;
}
}
Error:
Access to XMLHttpRequest at 'http://example.com' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Problem solved. There was no problem with the CORS, the problem was in the json.

django-cors-headers and nginx config: preflight response missing CORS headers

I use django-cors-headers 3.1.1 for handling the requests and responses between my Django-backend and Javascript-frontend apps. Transport is non-secured (i.e. http, not https).
When hosted locally, everything works fine. But after deploying on the server, I stopped seeing the CORS headers.
Here are headers in development:
and in production:
Error message:
Access to XMLHttpRequest at 'http://[HOST_IP]/api/assets/' from origin 'http://my_custom_domain.eu' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
My nginx configurations looks as follows:
server {
listen 80;
server_name [HOST_IP];
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 86400;
if ($request_method = 'OPTIONS') {
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /static/ {
autoindex on;
alias /home/ubuntu/[path_to_app]/site/static/;
}
}
The django-cors-headers’ settings are now identical in development and in production:
INSTALLED_APPS = (
…
"corsheaders",
…
)
MIDDLEWARE = [
…
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
…
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = ['DELETE','GET','OPTIONS','PATCH','POST','PUT']
On the client side I tried to add ‘'Access-Control-Request-Method’: ‘PUT’ header, but this was refused by the browser. There’s noting unusual in the client call:
axios({
method: 'put',
url: `${this.backendUrl}/api/assets/`,
data: formData,
headers: {
'Content-Type': 'application/octet-stream',
}
})
Also, I’m trying to host on the Amazon AWS EC2 for the first time, so perhaps there is some required AWS configuration I am not aware of. For example, is it necessary to enable CORS using the API Gateway? The documentation does not say so (‘If you are using the API Gateway Import API, you can set up CORS support using an OpenAPI file’).
The frontend application is hosted on a S3 bucket with the following CORS policy:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
What am I missing here? Is there some needed server-side (nginx especially) configuration?
Some other solutions I’ve tried:
I have doubts, whether the request/response origin is correct (e.g. APPEND_SLASH variable). But if this is the case, shouldn’t an error be raised when hosted locally?
I also tried setting proxy headers as in this question, but without knowing nginx very well this was doomed to fail.
I managed to solve this issue by changing 3 things:
AWS
I noticed that AWS documentation states:
CORS is already enabled for the Amazon EC2 API, and is ready for you
to use. You do not need to perform any additional configuration steps
to start using this feature. There is no change to the way that you
make calls to the Amazon EC2 API; they must still be signed with valid
AWS credentials to ensure that AWS can authenticate the requestor. […]
This is usually handled by AWS SDK or CLI, but in my case I used none of them, so I had to add AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. In my case I simply used aws4 library:
axios(aws4.sign({
accessKeyId: this.awsAccessKey,
secretAccessKey: this.awsSecretAccessKey,
method: 'put',
url: `${this.backendUrl}/api/assets/`,
data: formData,
body: JSON.stringify(formData),
service: 'ec2',
region: 'eu-central-1',
path: '/',
headers: {
'Content-Type': 'application/octet-stream'
}
}))
I’ve seen plenty of examples how to add AWS Signature v.4 without any additional dependency, though.
NGINX
In nginx configuration I placed all add_headers statements into conditional code-blocks. Idea came from this post.
server {
listen 80;
server_name [HOST_IP];
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/html; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, OPTIONS, POST, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /static/ {
autoindex on;
alias /home/ubuntu/analizy/be/site/static/;
}
}
Django-cors-header
Here it sufficed to add non-default headers.
from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = list(default_headers) + [
'X-Amz-Date',
]
Hope that this will help someone.

Using a Header to Filter Proxied Response Headers

I have an upstream server that often sets Cookie(s) by returning the "Set-Cookie" response header.
I would like to have an nginx proxy in front of said upstream server:
Browser => Nginx => Upstream
If the Browser => Nginx request had the header X-No-Cookies: true I'd like the response from Upstream => Nginx => Browser not to contain the Set-Cookie response header. If X-No-Cookies had any other value, I'd lie the Set-Cookie response header to be returned unaltered. I'm not able to change the response header behavior of the upstream server.
Currently my nginx config is as follows, pay specific attention to the use of the proxy_hide_header directive. I've also echoed the $proxy_hide_header variable in the X-No-Cookies response header.
map $http_x_no_cookies $proxy_hide_header {
default "";
"true" "Set-Cookie";
}
# Homepage
server {
listen 80;
server_name example.com;
location /api {
proxy_pass https://example.com/api;
proxy_hide_header $proxy_hide_header;
add_header "X-No-Cookies" $proxy_hide_header;
}
}
When I make a request with cURL:
curl \
http://example.com/api \
-H 'X-No-Cookies: true' \
-I
I get the following response headers:
Server: nginx/1.12.2
Date: Thu, 13 Dec 2018 02:26:41 GMT
Content-Type: application/json
Content-Length: 2255
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Expose-Headers: Content-Length
Set-Cookie: foo=bar; Max-Age=2592000; Expires=Sat, 12 Jan 2019 02:26:41 GMT; Path=/; Domain=example.com; Secure
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-No-Cookies: Set-Cookie
Whenever the proxy_hide_header is provided an nginx variable as an argument it seems to have no effect. If I swap the variable for a string ($proxy_hide_header substituted for "Set-Cookie") I get the desired behaviour - the Set-Cookie response header is omitted.
Edit: I've pushed the code for this question to GitHub
My original (non-working) implementation is here
Ivan Shatsky's solution is here
What an interesting challenge! Truly, $proxy_hide_header does not accept variables as its parameter and cannot be used inside an if blocks. Also we cannot use $upstream_... variables directly inside a location block because its values are not evaluated yet. Finally I found a solution. We always hide Set-Cookie header and then set it again if needed, values calculating through map expressions:
map $http_x_no_cookies $hide_cookies {
default "0";
"true" "1";
}
map $hide_cookies$upstream_http_set_cookie $cookies {
~^0(.*)$ $1;
}
upstream backend {
server example.com;
}
server {
listen 80;
server_name example.com;
location /api {
proxy_pass https://backend/api;
proxy_hide_header Set-Cookie;
add_header Set-Cookie $cookies;
}
}

Enabling CORS on nginx

I have followed this example to enable CORS on my API subdomain so that I can send requests to it from SwaggerUI. This is the output I get from running OPTIONS on that subdomain:
curl -i -X OPTIONS http://api.MYDOMAIN.com/v1/data/extraction
HTTP/1.1 204 No Content
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 18 Apr 2018 20:45:52 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-API-Key
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=UTF-8
Content-Length: 0
I'm stuck on where to go to figure out why in Chrome on my docs subdomain (same DOMAIN.com server) it still gives me this. Can anyone advise where I should look to?
I had a similar issue and couldn't get it to work. This setup finally worked for me. https://gist.github.com/Stanback/7145487 this is what it looks like. I just set $cors 'true' to test if it worked. It worked for me. This is all in the /location {...} area
set $cors '';
if ($http_origin ~ '^https?://(localhost|www\.yourdomain\.com|www\.yourotherdomain\.com)') {
set $cors 'true';
}
if ($cors = 'true') {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
# required to be able to read Authorization header in frontend
#add_header 'Access-Control-Expose-Headers' 'Authorization' always;
}
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
# required to be able to read Authorization header in frontend
#add_header 'Access-Control-Expose-Headers' 'Authorization' always;
# Tell client that this pre-flight info is valid for 20 days
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
All it came down to the fact that NGINX had used more_set_headers instead of add_header (it may've been that NGINX had this module enabled) and after that using one of the above examples with it made it working.
You might want to test a call to api.MYDOMAIN.com/v1/data/extraction with curl and a CORS origin header.
curl -i -X POST -H "Origin: http://docs.whatever.com" \
--verbose http://api.MYDOMAIN.com/v1/data/extraction
The response should come back with the header:
Access-Control-Allow-Origin: *
If that header does not come back with the response, chrome will throw an error like what you saw.
P.S. there is a mention in the error that nginx responded with a 404, which might have something to do with it.
The problem might well be that Access-Control-Allow-Origin: * and Access-Control-Allow-Credentials: true are incompatible - if you want to pass credentials, you will need to respond with Access-Control-Allow-Origin: {value-of-Origin-request-header} and Access-Control-Allow-Credentials: true.

Resources