What is CORS? How does it work and what does it do?

Cross-origin resource sharing (CORS) is an easy way to share resources and endpoints across the web. The same-origin security policy dictates that client side javascript can only collect data from the same domain. As in - example.com cannot load data from test.example.com (for CORS a subdomain is also another domain). Browsers limit most calls to the same origin for security reasons. Images, iframes, stylesheets and scripts are exempted from this rule. This limitation is made by the browser, not the website it is accessing. But it is the website you are accessing that dictates whether you can use the resources or not.

CORS is a way to tell the browser that it is okay to use data from another domain. The website that the browser calls acknowledges that the data can be accessed by setting the Access-Control-Allow-Origin header. This is set to the domain of where the browser is calling from. In turn the request of the browser which accesses the cross origin resource, contains an Origin header - which is the domain it is calling from. This way the browser knows that it is okay for the current website to get data from the cross domain - or deny it. The logic - whether or not the Access-Control-Allow-Origin is set, is done on the cross domain site.

If the data that the site is exposing should be public then the header can be set to "*". This will allow any domain to get data from the site.

CORS is simply a way to give browsers permission to use a resource from another domain.

A simplified version of how CORS works can be seen below:

Cors requests and headers

But why?

As mentioned CORS is here for security purposes, if it was not in place the following scenario would be possibe:

  • Bob browses the internet and encounters a malicious site.
  • The site makes a request to the website of the bank that Bob uses, since browers automatically sent along all cookies when making requests and Bob recently logged in, it is authenticated.
  • The malicious site can now use Bob's identity.

In old browsers that did not implement CORS the above was possible, however all modern browsers implement CORS (same-origin security policy).

Common errors

If you get one of the following errors:

  • "XMLHttpRequest cannot load {URL}. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '{Origin}' is therefore not allowed access."
  • "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at {URL}. This can be fixed by moving the resource to the same domain or enabling CORS."

Then most likely the server you are trying to access has not set the Access-Control-Allow-Origin header. Remember accessing the data directly in the browser will return the data just fine - since it accessed directly, and not through another domain. This often catches developers off guard.

Preflight and option calls

For modifying data, the specification for CORS mandates that a preflight (options) request is made. If approved, the browser sends the actual request, which is done automatically by the browser. This can seem odd and can have you asking why your browser is making an option request before the actual request (as it will not be in your code). This is all normal and part of the specification.

Browser support

CORS is supported by all modern browsers - except for Opera Mini (currently). If you cannot use CORS you can instead do a feature detection and use JSONP. JSONP is still a viable option if you wish to support older browsers. Most consider it somewhat a hack, but it is so widely used that it is more of a feature.

If you cannot use JSONP either, you can always make an endpoint on your own website. Which then calls the ressource. This will make your own endpoint (domain) act as a proxy. The browser will no longer call the external resource but call your own site which then calls the ressource.

That is it

Please leave a comment if you found this helpful!