CORS Goes Mainline

About 6 years ago Opera's Anne van Kesteren started working on a spec called "Access Control", which had been used in VoiceXML to allow limited cross-site access for cases where that didn't pose a security problem. After many years of working on the spec, in Opera, and with other browser developers, it is something the Web is starting to adopt - a real standard, now called CORS. Although it is still formally a working draft, it has been stabilising and getting deployed in test applications so we don't expect it to change a lot now.

This week, Opera integrated support for it into the core mainline, meaning it can start to be adopted in product builds - so look for it soon in a snapshot near you. ...

Cross-Origin Resource Sharing(CORS) has applications for XMLHttpRequest, EventSource and cross-origin image fetches. Here's a brief attempt at giving an overview of what it brings.

In its simple form, CORS requires the user agent to lace requests with an "Origin:" header when performing accesses outside of a same-origin boundary. The "Origin:" being the (protocol,server,port) of the originating content (e.g., http://sau.no) So, if content on sau.no accesses elg.no resources, the elg.no resource will verify that such access is allowed and include CORS headers in the response. (e.g., Access-Control-Allow-Origin: http://sau.no) The user agent then verifies that the attempted CORS access was indeed permitted from the given origin before giving the green light.

That's the simple form. Full CORS also handles any method and header along with optionally using credentials/cookies for such cross-origin accesses. To quote the introduction of the current W3C working draft:

<blockquote class="bbquote"><p> If a resource author has a simple text resource residing at http://example.com/hello which contains the string "Hello World!" and would like http://hello-world.example to be able to access it, the response combined with a header introduced by this specification could look as follows:
<pre> Access-Control-Allow-Origin: http://hello-world.example

Hello World!</pre>
Using XMLHttpRequest a client-side Web application on http://hello-world.example can access this resource as follows:
<pre>var client = new XMLHttpRequest(); client.open("GET", "http://example.com/hello") client.onreadystatechange = function() { /* do something */ } client.send()</pre>
It gets slightly more complicated if the resource author wants to be able to handle cross-origin requests using methods other than simple methods. In that case the author needs to reply to a preflight request that uses the OPTIONS method and then needs to handle the actual request that uses the desired method (DELETE in this example) and give an appropriate response. The response to the preflight request could have the following headers specified:
<pre>Access-Control-Allow-Origin: http://hello-world.example Access-Control-Max-Age: 3628800 Access-Control-Allow-Methods: PUT, DELETE</pre>
The Access-Control-Max-Age header indicates how long the response can be cached, so that for subsequent requests, within the specified time, no preflight request has to be made. The Access-Control-Allow-Methods header indicates the methods that can be used in the actual request. The response to the actual request can simply contain this header:
<pre>Access-Control-Allow-Origin: http://hello-world.example</pre>
The complexity of invoking the additional preflight request is the task of the user agent. Using XMLHttpRequest again and assuming the application were hosted at http://calendar.example/app the author could use the following ECMAScript snippet:
<pre>function deleteItem(itemId, updateUI) { var client = new XMLHttpRequest() client.open("DELETE", "http://calendar.example/app") client.onload = updateUI client.onerror = updateUI client.onabort = updateUI client.send("id=" + itemId) } </pre></p></blockquote>
The CORS algorithm/protocol is clearly of a general nature, and has applicability in a number of settings already. The current integration adds it to XMLHttpRequest, EventSource, and cross-origin image fetches. The last part allows use of cross-origin images and textures on Canvas and WebGL. Adding the CORS security checks to other contexts will be done over time.

As part of this work we have done a little general upgrade of our XMLHttpRequest and we now support EventTarget. The modernisation continues, and we hope to round out our implementation of the XMLHttpRequest2 specification soon.