What does the absence of the "origin" HTTP header mean, and how can this case be handled safely?

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 only Vary: 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 .

Scroll to Top