An overview of CORS
Before we dive into any code, or start talking about cross-origin requests specifically, let’s take a moment to define what we mean by the term origin.
Basically, if two URLs have the same scheme, host and port (if specified) they are said to share the same origin. To help illustrate this, let’s compare the following URLs:
| URL A | URL B | Same origin? | Reason |
|---|---|---|---|
https://foo.com/a |
http://foo.com/a |
No | Different scheme (http vs https) |
http://foo.com/a |
http://www.foo.com/a |
No | Different host (foo.com vs www.foo.com) |
http://foo.com/a |
http://foo.com:443/a |
No | Different port (no port vs 443) |
http://foo.com/a |
http://foo.com/b |
Yes | Only the path is different |
http://foo.com/a |
http://foo.com/a?b=c |
Yes | Only the query string is different |
http://foo.com/a#b |
http://foo.com/a#c |
Yes | Only the fragment is different |
Understanding what origins are is important because all web browsers implement a security mechanism known as the same-origin policy. There are some very small differences in how browsers implement this policy, but broadly speaking:
A webpage on one origin can embed certain types of resources from another origin in their HTML — including images, CSS, and JavaScript files. For example, doing this in your webpage is OK:
<img src="http://anotherorigin.com/example.png" alt="example image">
A webpage on one origin can send data to a different origin. For example, it’s OK for an HTML form in a webpage to submit data to a different origin.
But a webpage on one origin is not allowed to read data from a different origin.
The key thing here is the final bullet-point: the same-origin policy prevents a (potentially malicious) website on another origin from reading (possibly confidential) information from your website.
It’s important to emphasize that cross-origin sending of data is not prevented by the same-origin policy, despite also being dangerous. In fact, this is why CSRF attacks are possible and why we need to take additional steps to prevent them — such as using SameSite cookies and CSRF tokens.
As a developer, the time that you’re most likely to run up against the same-origin policy is when making cross-origin requests from JavaScript running in a browser.
For example, let’s say that you have a webpage at https://foo.com containing some front-end JavaScript code. If this JavaScript tries to make an HTTP request to https://bar.com/data.json (a different origin), then the request will be sent and processed by the bar.com server, but the user’s web browser will block the response so that the JavaScript code from https://foo.com cannot see it.
Generally speaking, the same-origin policy is an extremely useful security safeguard. But while it’s good in the general case, in certain circumstances you might want to relax the restriction.
For example, if you have an API at api.example.com and a trusted JavaScript front-end application running on www.example.com, then you’ll probably want to allow cross-origin requests from the trusted www.example.com domain to your API.
Or perhaps you have a completely open public API, and you want to allow cross-origin requests from anywhere so it’s easy for other developers to integrate with their own websites.
Fortunately, most modern web browsers allow you to allow or disallow specific cross-origin requests to your API by setting Access-Control headers on your API responses. We’ll explain exactly how to do that and how these headers work over the next few chapters of this book.