blog.iankulin.com

CORS, What is it good for?

Imagine you have two browser tabs open, one to your bank, and one to evil-site.com

┌─────────┐┌──────────────┐              
│   BANK  ││  EVIL-SITE   │              
├─────────┴┴              ┴────────┐
│                                  │
│                                  │
│                                  │
│                                  │
│                                  │
└──────────────────────────────────┘

evil-site.com, knowing you’re probably authenticated to your bank, sends a request to it for some data.

Luckily, your browser complies with the Same-origin policy and won’t let the evil-site.com page see the results of this query when the response arrives.

The basic rule of Same-origin policy is that the Javascript in a web page can only read responses from the same origin where the origin is the combination of scheme (http vs https), hostname, and port.

What URLs have the same origin as https://evil-site.com?

URL / ResourceSame originWhy
https://evil-site.com/pageYesSame protocol, host, and port
https://evil-site.com:443/apiYesPort 443 matches HTTPS
https://sub.evil-site.comNoDifferent host/subdomain
http://evil-site.comNohttp vs https protocol
https://evil-site.com:8443NoDifferent port
https://evil-site.orgNoDifferent domain
https://www.evil-site.comNoDifferent www subdomain

The purpose of the same-origin policy (which has been around since about 1995) is to stop a malicious script on one page accessing the data on another page.

  • It’s a browser protocol - it doesn’t apply to curl or other methods of fetching resources
  • It’s a Javascript thing - you can still fetch resources such as images, scripts, css etc from other origins in your page using HTML tags.

CORS

So the same-origin policy is a pretty great sensible restriction for preventing a foreseeable and real problem in allowing web sites to run code. But it does cause some pain. Imagine this: We have a pretty React front-end application on our company website at https://example.com and we want it to fetch data from https://api.example.com It can make the request, and https://api.example.com can send the data, but our application can never see it because the browser says ‘hang on, this is against my same-origin policy because these two addresses are not the same origin’.

┌─────────────────────┐    ┌─────────────────────────┐
│                     │    │                         │
│                     │    │                         │
│ https://example.com │    │ https://api.example.com │
│                     │    │                         │
│                     │    │                         │
└─────────────────────┘    └─────────────────────────┘

This is obviously bad, so what we need is a safe way to get around the same-origin policy for just this site. https://api.example.com needs some way to say “I’m happy for https://example.com to fetch my data even though we’re on different origins”.

Welcome to Cross Origin Resource Sharing (CORS).

All https://api.example.com has to do is set a header in its response so that the browser knows this is allowed. The headers in the response from https://api.example.com would include:

Access-Control-Allow-Origin: https://example.com

or perhaps if https://api.example.com is a public API that’s happy for anyone to use it’s data, it might say:

Access-Control-Allow-Origin: *