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

Cross-origin ressource sharing (CORS) is an easy way to share resources and endpoints accross the web. The same-origin security policy dictates that clientside javascript can only collect data from the same domain. As in - example.com cannot load data from test.example.com. 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 ressources 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 ressource, 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 is 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 ressource 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. Let's see what would be possible if client side scripting could call any ressource:

  • Bob browses the internet and encounters a malicious site.
  • The site uses bob's identity, and using client site scripts it can access the website of his bank.
  • Because the site is not blocked by the browser it can make requests to the bank.

Because of the same-origin security policy it is not possible to do the above. Of course your bank would not let it be accessed from the outside. Let say that the bank had several domains, the domains would not be able to access one another. But they would be able to do so, using CORS!

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 it most likely means that the server you are accessing 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) call is made. If approved, the browser sends the actual request. This is done automatically by the browser. Which can seem odd and can have you asking why your browser is making an option call before the actual ajax call (as it will not be in your code). This is normal and part of the specification.

I did not include preflight in my earlier explanation as it is handled by the browser.

##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 norm.

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 ressource but call your own site which then calls the ressource.

That is it

Please write in the comments if you found this helpful!