CORS - cross origin requests in the browser

Written by: Michael Neale

Every web developer, and certainly every javascript-heavy developer, would know about the same origin policy - meaning that web apps can only load data from the servers they were served from (ie, in javascript) - not "other" servers - ostensibly for security reasons.

Single origin: nice for scotch, a challenge for web dev.

These same fine developers should also know that you can "get around" this in JS via JSON-P - basically programmatically create a script tag that fetches the "resource" from the "other" server - and evals it (browsers are allowed in most cases to load "files" from other servers).

This is a nasty and elegant hack, but limited.

Another approach is to use a proxy service from the server that served up the web app:

This is ok - and gives you a lot of control - but gets a bit crazy after a while, and ads latency.

It is increasingly common for apps to offer up JSON data, and with things like OpenID and OAuth it is becoming nicer and nicer to do the "integration" entirely in the web app, in javascript!

This is done via CORS - something all current browsers support. Some headers are added to the "other" servers - and then you can happily do direct calls - even POST/PUT etc (json-p is limited to GET)

Headers such as "access-allow-origin" say what domains can access the "other server", even what headers are shown etc - in theory giving the "other server" some say in how its data is used and when.

This is relatively simple - we have been rolling it out in various places for a while - with one main gotcha: whilst the spec says you can list domains that are allowed - in reality - often only one is supported. So you need some server side code "white listing" who is requesting it, and adding the appropriate header in. Kind of unpleasant, but doable (if it wasn't for this, it could be fairly static web server configuration).

This site was setup as a way to advocate for CORS use and adoption.

Some other gotchas: You have to return the header as it is required by the "preflight checks" - these are done via the browser doing "HEAD" requests - it then remembers if you are allowed. These "preflight checks" happen outside of the dev tools view in chrome - this can make debugging hard, but it is a known chrome bug.

Why not use "*" for allowing all origins: maybe this is a security risk. If the "other server" has authorised the user to access the service, then a malicious 3rd party website could then use a script to fetch the data - and, give, the browser could well pass along the cookies - act on the users behalf.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.