Instantly share code, notes, and snippets.

Embed
What would you like to do?
Slightly tighter CORS config for nginx
#
# Slightly tighter CORS config for nginx
#
# A modification of https://gist.github.com/1064640/ to include a white-list of URLs
#
# Despite the W3C guidance suggesting that a list of origins can be passed as part of
# Access-Control-Allow-Origin headers, several browsers (well, at least Firefox)
# don't seem to play nicely with this.
#
# To avoid the use of 'Access-Control-Allow-Origin: *', use a simple-ish whitelisting
# method to control access instead.
#
# NB: This relies on the use of the 'Origin' HTTP Header.
location / {
if ($http_origin ~* (whitelist\.address\.one|whitelist\.address\.two)) {
set $cors "true";
}
# Nginx doesn't support nested If statements. This is where things get slightly nasty.
# Determine the HTTP request method used
if ($request_method = 'OPTIONS') {
set $cors "${cors}options";
}
if ($request_method = 'GET') {
set $cors "${cors}get";
}
if ($request_method = 'POST') {
set $cors "${cors}post";
}
if ($cors = "true") {
# Catch all incase there's a request method we're not dealing with properly
add_header 'Access-Control-Allow-Origin' "$http_origin";
}
if ($cors = "trueget") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($cors = "trueoptions") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# 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;
}
if ($cors = "truepost") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
@algal

This comment has been minimized.

Show comment
Hide comment
@algal

algal Apr 29, 2013

This is very great. I commented it, updated various parts (e.g., not returning preflight response headers to actual requests), and put the result here: https://gist.github.com/algal/5480916 .

algal commented Apr 29, 2013

This is very great. I commented it, updated various parts (e.g., not returning preflight response headers to actual requests), and put the result here: https://gist.github.com/algal/5480916 .

@Ry4an

This comment has been minimized.

Show comment
Hide comment
@Ry4an

Ry4an Aug 9, 2013

Thanks for this. I think you want a $ at the end of the regex on line 18. Without it my site http://whitelist.address.one.evil.com will pass and show up in the Access-Control-Allow-Origin header.

Ry4an commented Aug 9, 2013

Thanks for this. I think you want a $ at the end of the regex on line 18. Without it my site http://whitelist.address.one.evil.com will pass and show up in the Access-Control-Allow-Origin header.

@jmenchacavr

This comment has been minimized.

Show comment
Hide comment
@jmenchacavr

jmenchacavr Aug 5, 2014

$http_origin is empty on my system. Is there some mechanism needed to have this available?

jmenchacavr commented Aug 5, 2014

$http_origin is empty on my system. Is there some mechanism needed to have this available?

@kaitsche

This comment has been minimized.

Show comment
Hide comment
@kaitsche

kaitsche commented Nov 18, 2014

curl -I -X OPTIONS -H "Origin: http://www.example.com" http://www.yourdomain.com

@spyrospph

This comment has been minimized.

Show comment
Hide comment
@spyrospph

spyrospph Mar 12, 2015

Hi,

I have observed when I use an if statement within a location then nginx returns a 404.

So the below does not work:

if ($cors = "true") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
}

try_files $uri $uri/ /index.php?$args;

causes nginx to not reach the try_files directive and return a 404.

Anyone else with this issue?

spyrospph commented Mar 12, 2015

Hi,

I have observed when I use an if statement within a location then nginx returns a 404.

So the below does not work:

if ($cors = "true") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
}

try_files $uri $uri/ /index.php?$args;

causes nginx to not reach the try_files directive and return a 404.

Anyone else with this issue?

@mox601

This comment has been minimized.

Show comment
Hide comment
@mox601

mox601 Mar 17, 2015

@spyrospph I have the same problem, and it's also documented at IfIsEvil.
imho, if there are no ways to add cors headers without using ifs, don't use nginx.

mox601 commented Mar 17, 2015

@spyrospph I have the same problem, and it's also documented at IfIsEvil.
imho, if there are no ways to add cors headers without using ifs, don't use nginx.

@thoughtless

This comment has been minimized.

Show comment
Hide comment

thoughtless commented Mar 18, 2015

@lainjiang

This comment has been minimized.

Show comment
Hide comment
@lainjiang

lainjiang Feb 26, 2016

What does 'X-Mx-ReqToken' header actually do? I see it in all CORS tutorials for nginx but can't find any info otherwise.

lainjiang commented Feb 26, 2016

What does 'X-Mx-ReqToken' header actually do? I see it in all CORS tutorials for nginx but can't find any info otherwise.

@c-shang

This comment has been minimized.

Show comment
Hide comment
@c-shang

c-shang Jan 11, 2017

This is very helpful

c-shang commented Jan 11, 2017

This is very helpful

@bfricka

This comment has been minimized.

Show comment
Hide comment
@bfricka

bfricka Jan 4, 2018

According to nginx, if shouldn't be used in a location block like this.

bfricka commented Jan 4, 2018

According to nginx, if shouldn't be used in a location block like this.

@thiagof

This comment has been minimized.

Show comment
Hide comment
@thiagof

thiagof Feb 13, 2018

Correct ^
All this ifs are different levels and should not work together according to add_header usage docs.

thiagof commented Feb 13, 2018

Correct ^
All this ifs are different levels and should not work together according to add_header usage docs.

@michalzvolanek

This comment has been minimized.

Show comment
Hide comment
@michalzvolanek

michalzvolanek Mar 29, 2018

Very well, thanks

michalzvolanek commented Mar 29, 2018

Very well, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment