I faced the same problem with a Magento setup with Nginx.
I share you my working configuration which solve this CORS problem for an headless Magento use case (API).
By defaut Magento do not accept OPTIONS call with API. So a workaround is to return a 200 response for all OPTIONS call on API :
location /rest {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,Authorization,X-CustomHeader,Keep-Alive,User-Agent,Origin,Referer,X-HTTP-Method-Override,X-Accept-Charset,X-Accept,Accept,Access-Control-Request-Method,Access-Control-Request-Headers,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 200;
}
}
Some Allow-Headers is not mandatory, try to test which are on your case.
Then add headers on all other requests :
location ~ (index|get|static|report|404|503)\.php$ {
.....
.....
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,Authorization,X-CustomHeader,Keep-Alive,User-Agent,Origin,Referer,X-HTTP-Method-Override,X-Accept-Charset,X-Accept,Accept,Access-Control-Request-Method,Access-Control-Request-Headers,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type' always;
}
Make sure to keep the always option in order to add these headers for response code other than : 200, 201, 204, 206, 301, 302, 303, 304, 307, or 308
Make sure you do not have basic auth authentication behind. If not, update the configuration in order to allow the OPTIONS CORS request made from your browser.