What is the difference between
add_header "Access-Control-Allow-Origin" *;
and
add_header "Access-Control-Allow-Origin" $http_origin always;
If I used both in a NGINX config what are the implications of that? Or can it only be one or the other?
Previously I had a NGINX config that only had * but had a user encounter a problem where CORS was not working until it was changed to $http_origin always, and I am unsure of the differences and why changing it worked.
add_header "Access-Control-Allow-Origin" $http_origin always;
is unnecessary at best and dangerous at worst.
[I] had a user encounter a problem where CORS was not working until it was changed to
$http_origin always[...]
You likely hit the so-called wildcard exception. In short, the wildcard (*) is incompatible with credentialed access, e.g. requests that carry cookies.
When your CORS configuration allows cross-origin credentialed access, unconditionally reflecting the request's origin in the Access-Control-Allow-Origin is dangerous because it expose your users to cross-origin attacks:
Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true
Instead, you should an allowlist of Web origins you really trust.
(Most CORS middleware libraries allow you to do that easily, which is why I recommend implementing CORS at the application level rather than at the reverse-proxy level.)
And when your CORS configuration only allows anonymous (as opposed to credentialed) access, unconditionally reflecting the request's origin in the Access-Control-Allow-Origin is unnecessary, because you might as well use the wildcard:
Access-Control-Allow-Origin: *
These are just two different ways to specify origins:
| Header Value | Description |
|---|---|
"Access-Control-Allow-Origin" * |
This will allow any origin to access the resource. I'm guessing you already know this but just in case an origin is the combination of protocol, domain, and port. So http://example.com, https://example.com, and http://example.com:8080 are all different origins. |
"Access-Control-Allow-Origin" $http_origin always |
This is saying that the only thing that has access to the resource is the origin that made specifically made the request |
Having both in your nginx config is probably not a great idea since the CORS spec says to have a single Access-Control-Allow-Origin header, I believe. So this might cause conflicts with your setup. It is worth noting that nginx does try to handle this case for you by using the value from the last header you set.
I'm guessing that you were having a problem with * because some browsers and apps do not accept a wild card for security reasons. I have usually seen this when credentials are involved (like cookies or HTTP auth). So when you set the header to the exact origin as the request, it is interpreted as a bit more restrictive and secure than *.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With