Cross-origin resource sharing (CORS) allows scripts in third-party web applications to access resources in a domain.

Why is it needed?

Due to the same-origin policy (SOP) it isn't possible for a web application to request resources hosted in another web application using a script (SOP doesn't apply to CSS or images). CORS allows to soften this restriction.

What's an origin?

An origin is protocol+domain+port: https://example.tredecimal.com:443 if any of the three isn't exactly the same it isn't considered the same origin, subdomains are also considered a different origin (due to the domain changing). The origin is sent as a header on requests.

How does it work?

The client browser sends a GET request with the extra Origin header, if the server allows CORS, it returns an Access-Control-Allow-Origin header containing either the URL of the origin or a wildcard (if all origins are allowed). It can also return a Access-Control-Allow-Credentials if access to private parts is needed, this header will allow cookies, TLS user certs or authorization headers to be used.

What problems does it have

  • It is not possible to define more than one origin per CORS endpoint.
  • You can use different domains/origins for different endpoints of your application but not multiple domains for the same endpoint.
  • You cannot use the Allow-Credentials header when the wildcard is used in the Allow-Origin header. Due to the above restrictions, programmers and frameworks have found ways to allow multiple origins/domains to access the same endpoint while being able to use the Allow-Credentials header.

How can CORS be used while allowing multiple origins?

There are two ways, an insecure one, using the null Origin and an error-prone one using "dynamic origin validation".

Null is a special case of the "one domain" case. All origins can simulate being null (using a sandboxed iframe or a data-URL among other ways) and due to it falling into the "one domain" case it allows using the Allow-Credentials header. That has security implications. If anyone can fake a null origin, that means an attacker can too. In a way, it's like a more insecure wildcard.

Dynamic origin validation when correctly implemented can be both useful and secure. It's recommended to have a whitelist of fully qualified origins and compare the incoming Origin to them byte-for-byte . Using regex or matching only the beginning or end of the origin is very error-prone, can cause a security risk and should be avoided.

Of course it would be better if the specification simply allowed multiple domains in a secure way so each framework wouldn't need to write their own dynamic origin validation.

Misc

  • Using the vary: Origin header is a good idea when the response depends on the requester. When you use a CDN or something that can cache the response it avoids caching that.
  • Requests apart from GET and POST will get pre-flight.