Access-Control-Allow-Origin Multiple Origin Domains?
Solution 1
Sounds like the recommended way to do it is to have your server read the Origin header from the client, compare that to the list of domains you would like to allow, and if it matches, echo the value of the Origin
header back to the client as the Access-Control-Allow-Origin
header in the response.
With .htaccess
you can do it like this:
# ----------------------------------------------------------------------
# Allow loading of external fonts
# ----------------------------------------------------------------------
<FilesMatch "\.(ttf|otf|eot|woff|woff2)$">
<IfModule mod_headers.c>
SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header merge Vary Origin
</IfModule>
</FilesMatch>
Solution 2
Another solution I'm using in PHP:
$http_origin = $_SERVER['HTTP_ORIGIN'];
if ($http_origin == "http://www.domain1.com" || $http_origin == "http://www.domain2.com" || $http_origin == "http://www.domain3.com")
{
header("Access-Control-Allow-Origin: $http_origin");
}
Solution 3
This worked for me:
SetEnvIf Origin "^http(s)?://(.+\.)?(domain\.example|domain2\.example)$" origin_is=$0
Header always set Access-Control-Allow-Origin %{origin_is}e env=origin_is
When put in .htaccess
, it will work for sure.
Solution 4
I had the same problem with woff-fonts, multiple subdomains had to have access. To allow subdomains I added something like this to my httpd.conf:
SetEnvIf Origin "^(.*\.example\.com)$" ORIGIN_SUB_DOMAIN=$1
<FilesMatch "\.woff$">
Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN
</FilesMatch>
For multiple domains you could just change the regex in SetEnvIf
.
Solution 5
Here's how to echo the Origin header back if it matches your domain with Nginx, this is useful if you want to serve a font multiple sub-domains:
location /fonts {
# this will echo back the origin header
if ($http_origin ~ "example.org$") {
add_header "Access-Control-Allow-Origin" $http_origin;
}
}
Thomas J Bradley
Professor and developer of the Open Web from Ottawa, Canada
Updated on July 08, 2022Comments
-
Thomas J Bradley almost 2 years
Is there a way to allow multiple cross-domains using the
Access-Control-Allow-Origin
header?I'm aware of the
*
, but it is too open. I really want to allow just a couple domains.As an example, something like this:
Access-Control-Allow-Origin: http://domain1.example, http://domain2.example
I have tried the above code but it does not seem to work in Firefox.
Is it possible to specify multiple domains or am I stuck with just one?
-
sam over 10 years
-
Daniel W. about 10 yearsUsing the most recent Firefox, neither comma seperated, nor space seperated domains did work. Matching against a list of domains and putting a single host in the headers is still better security and does work properly.
-
Alex W about 9 yearsIf you're struggling with this for HTTPS, I found a solution.
-
The Red Pea over 6 years@sam or "*" ?
shared based by returning the value of the Origin request header, "*", or "null"
-
klues over 5 yearsimportant note: allowing only cretain domains in the
Access-Control-Allow-Origin
header does not mean that other domains cannot trigger a method on this endpoint (e.g. REST API method). It just means that disallowed origins cannot use the result in javascript (browser ensures this). For restricting access to an endpoint for specific domains use a server-side request filter that e.g. returns HTTP 401 for disallowed domains. -
Null almost 5 yearsYou should always append
Vary: Origin
header when you want to use multiple URLs, see: fetch.spec.whatwg.org/#cors-protocol-and-http-caches
-
-
pwes over 13 yearsThe trick looks promising, but it doesn't work in FF 3.6.13. What I observe is that two headers with the same name are joined into one, with values separated with a comma -- and it doesn't work, as OP posted. I observed the headers in LiveHTTPHeaders and FireBug.
-
B T about 13 yearsSee, when I did it, I did "Header set ..." rather than "Header add ..." - seems to work for me. Firefox 3.6.16
-
Sairam over 11 yearsThis is not allowed and does not work in FF - bugzilla.mozilla.org/show_bug.cgi?id=671608
-
Jack James about 11 yearsthere's a variation on this which seems to work: stackoverflow.com/questions/9466496/…
-
ErJab almost 11 yearsJust spent two hours trying to fix an issue related to CORS and it turns out that it was because of multiple Access-Control-Allow-Origin headers. I removed the multiple Access-Control-Allow-Origin headers and it started working. So this is not the right answer despite the number of votes. Use this method instead to support multiple domains: stackoverflow.com/a/1850482/123545
-
Danger about 10 yearsYou will in fact get an error message in the log from the latest Chrome browser as of now, telling you that it's ignoring the Access-Control-Allow-Origin header because there are multiple values.
-
AlexChaffee almost 10 yearsNope. From developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS : "A returned resource may have one Access-Control-Allow-Origin header" .. and from w3.org/TR/cors/#access-control-allow-origin-response-header : "Rather than allowing a space-separated list of origins, it is either a single origin or the string "null"" (first I've heard of "null" here btw)
-
Lior over 9 yearsThe specs clearly say that multiple values will cause the CORS algorithm to fails. So this isn't correct.
-
Radley Sustaire over 9 yearsAlso confirming this is incorrect. Using this to serve CSS to four domains, I receive an error in Chrome's log "[...] header contains multiple values 'aaa.com, bbb.com', but only one is allowed". It does not matter if you define it as one header, or multiple, or using
add
vs.set
. It just doesn't work. -
Mike Kormendy about 9 yearsI like this option and combined/modified it with the implementation that @George has. Sometimes servers don't have a2enmod available, so all you have to do is check your main httpd.conf to see if the line: LoadModule headers_module modules/mod_headers.so is uncommented.
-
spazm about 9 years'serving ads over ssl' links to the spec w3.org/TR/cors/#access-control-allow-origin-response-header which adds a note, "In practice the origin-list-or-null production is more constrained. Rather than allowing a space-separated list of origins, it is either a single origin or the string "null".
-
indiv about 9 yearsMy origin had a port number, so I modified the regular expression to include that:
^http(s)?://(.+\.)?example\.com(:\d+)?$
-
Bob Aman about 9 yearsWhile it's important to note that detail, when a specification says "In practice", it doesn't mean that it's only valid to do it that way. It means that if you do it that way, you may run into problems because the majority of implementors either implement the spec incorrectly or incompletely. The specification does allow for a space-separated list of origins, which you can see here in the EBNF under
origin-list
: tools.ietf.org/html/rfc6454#section-7.1 -
Tom about 4 years
Access-Control-Allow-Credentials: true
is not allowed with wildcardAccess-Control-Allow-Origin: *
. Set a specific<origin>
instead. -
timhc22 about 4 years@Tom, yea, not sure why that was in there, I can't remember, but I might have copied it from the defaults that were added on AWS? Thanks for pointing that out though.
-
MrWhite over 3 yearsShould probably check that
$request_headers['Origin'];
exists, otherwise any direct requests are going to trigger an E_NOTICE. -
Ben Winding about 3 yearsHow would you add wildcard subdomains like:
*.example.com
or wildcard ports like:localhost:*
-
Ben Winding about 3 yearsFor anyone wondering you can do
(.+\.google.com)
instead of(google.com|staging.google.com)
-
Almenon about 3 years
-
Ahmad Vaqas Khan about 3 yearsGreat. Helped me.
-
chichilatte over 2 yearsHandy to have an example for multiple domains:
^(https?:\/\/localhost:\d+)$|^(https?:\/\/.+\.yourdomain\.com)$
Here's it in action... regex101.com/r/GZHTLB/1 It's crazy gobbledegook but that regex101 site helps decipher it all. -
Héctor over 2 yearsHow would this behave if there is no match? Which would be the output of
Access-Control-Allow-Origin
? -
jub0bs over 2 yearsThat regex is not well designed; in particular, insecure origins (using the
http
scheme) shouldn't be allowed, and DNS label separators should be escaped (\.
instead of.
); otherwise, an attacker could for instance buy thedevelopmentzgoogle.com
domain and mount cross-origin attacks from there. -
CodeChari over 2 yearsHTTP_ORIGIN is not reliable, see stackoverflow.com/questions/41231116/…
-
iWasCloud about 2 yearsDO not use this in production, its not safe.
-
iWasCloud about 2 yearsDO not use this in production, its not safe.
-
suddjian almost 2 yearsany
.
in the domain needs to be escaped, otherwise it matches any character. Also, you can have just one if statement instead of using a variable