One of the new features recently announced for Windows Azure storage as part of the 2013-08-15 version is support for Cross Origin Resource Sharing (CORS). This post explains what CORS is, and includes a simple example of how to use it.
This error occurs because web browsers implement the same-origin policy security restriction that prevents a web page from calling an API in a different domain from the domain the page comes from. In this example, a client-side script in page from the localhost:56309 domain was attempting to call to a REST API in the domdec.blob.core.windows.net domain, the browser detected this potential security issue and prevented the request from completing.
Cross-Origin Resource Sharing (CORS) allows you to configure a set of rules that define exceptions to the same-origin policy. In this example, I want a set of rules that will allow calls from client-side script in the localhost:56309 domain to call an API in the domdec.blob.core.windows.net domain (my Windows Azure storage services). To do this, I must add some configuration to the domdec.blob.core.windows.net domain: this will enable the browser to make an initial call to the domdec.blob.core.windows.net domain to verify that it is permitted to call the API. You can see this happening here in another screenshot from the developer tools in Chrome:
This shows an initial OPTIONS request that checks whether or not the cross-origin PUT request will succeed.
At present, there is no UI for configuring CORS rules for your Windows Azure storage services, so for now you need to write a small amount of code. The following code sample shows how to configure a simple CORS rule that allows client-side code from the localhost:56309 domain to make PUT and GET calls to the BLOB API.
You can find full details of the various properties of a CORS rule at Cross-Origin Resource Sharing (CORS) Support for the Windows Azure Storage Services. In this example, I’m using a wildcard for the headers than can be submitted from the client, and a partial wildcard for the headers that are exposed to the client. I’m specifying that only GET and PUT requests are permitted, that requests must come from the localhost:56309 domain, and that requests are permitted for five seconds after the OPTIONS request was made. You can have up to five rules for each storage service (blobs, tables, queues) in your storage account.
The client-side code that makes the calls is slightly complicated because of the Windows Azure storage authentication requirements. For this example, I’ve chosen to use Shared Access Signatures (SAS) to enable temporary read and write access on a private blob. I have a simple WebAPI service (hosted at localhost:56309) that generates a shared access signature that’s good for two minutes.
As you can see, the client doesn’t need to do anything special to work with CORS: most modern browsers provide full support for CORS and look after all the handshaking for you.
There’s a useful page on Wikipedia that provides general background information about the CORS standard: Cross-origin resource sharing.