Question:
I know that the absence of the origin
header is a possible case.
I can assume that this header does not matter when we distribute content to everyone, regardless of origin. But probably more often we want to give content only to some trusted sources. I believe that in this case, when origin
is not specified, we should return a Bad Request
error.
In addition, we need this blank if we want to support subdomains. Probably in this case, you also need to return Bad Request
if origin
is not specified.
This is all I know about origin
at the moment.
In this question, I don’t even ask you not to write any code, I only ask you to explain some theoretical data, on the basis of which I myself will compose an algorithm and write code.
Answer:
CORS restrictions are triggered at the browser level. Therefore, from the server side, you need to give the correct headers, and nothing else. Let's go from simple to more complex.
One domain
To allow CORS from the address https://site.ru
, you need to send such headers (this is a config from Nginx).
add_header "Access-Control-Allow-Origin" "https://site.ru" always;
add_header "Access-Control-Allow-Headers" "Content-type, Authorization, X-Requested-With, Accept" always;
add_header "Access-Control-Allow-Methods" "GET, POST, PUT, PATCH, DELETE, OPTIONS" always;
All domains
I can assume that this header does not matter when we distribute content to everyone, regardless of origin
Yes, in this case "Access-Control-Allow-Origin: *"
.
Only selected domains
But probably more often we want to give content only to some trusted sources
You cannot take and list the allowed domains separated by commas. Only one. Therefore Access-Control-Allow-Origin
must depend on the Origin
header that the browser sends. This can be configured either on the web server or in the application ( header('....')
in PHP).
I know that the absence of the origin header is a very possible case.
Yes. The browser may not send this header, because there is no CORS request ( https://site.ru/
requests https://site.ru/api
, Origin is not sent, since the domain is the same, send Origin from the point of view of browser logic useless).
I believe that in this case, when the origin is not specified, we should return a Bad Request error
That's why no, you can't do that. Right:
- Origin is specified – compare with the list of allowed ones – give the value as in Origin, if + in the list add
Vary: Origin
(more on that below). If not – the main domain, let the CORS ban work - Origin is not specified – we do not return
Access-Control-Allow-*
, we return onlyVary: Origin
(more on that below).
Vary: Origin
And here's another surprise: the browser caches the Access-Control-Allow-*
. Therefore, it may well be such an unpleasant situation . Or another. Remember that for a browser, CORS occurs when either the protocol, port, or domain is different. In all cases where one header depends on another, the Vary: ...
header must be used.
If Access-Control-Allow-*
depends on Origin
(case for multiple domains), then add Vary: Origin
.
But if there is only one domain (the one where requests will go from), you don’t need to add Vary: Origin
, since it’s unnecessary .