Implementing CORS in Cornice ############################ :date: 22-01-2013 :slug: cross-origin-in-cornice :status: draft For security reasons, it's not possible to do cross-domain requests. In other words, if you have a page served from the domain `lolnet.org`, it will not be possible for it to get data from `notmyidea.org`. Well, it's possible, using tricks and techniques like `JSONP `_, but that doesn't work all the time (see `the section below <#how-this-is-different-from-jsonp>`_). I remember myself doing some simple proxies on my domain server to be able to query other's API. Hopefuly, there is a nicer way to do this, namely, "Cross Origin Resource-Sharing", or `CORS `_. You want an icecream? Go ask your dad first. ============================================ If you want to use CORS, you need the API you're querying to support it; on the server side. The HTTP server need to answer to the `OPTIONS` verb, and with the appropriate response headers. `OPTIONS` is sent as what the authors of the spec call a "preflight request"; just before doing a request to the API, the *User-Agent* (the browser most of the time) asks the permission to the resource, with an `OPTIONS` call. The server answers, and tell what is available and what isn't: .. image:: |filename|/images/cors_flow.png :alt: The CORS flow (from the HTML5 CORS tutorial) - 1a. The User-Agent, rather than doing the call directly, asks the server, the API, the permission to do the request. It does so with the following headers: - **Access-Control-Request-Headers**, contains the headers the User-Agent want to access. - **Access-Control-Request-Method** contains the method the User-Agent want to access. - 1b. The API answers what is authorized: - **Access-Control-Allow-Origin** the origin that's accepted. Can be `*` or the domain name. - **Access-Control-Allow-Methods** a *list* of allowed methods. This can be cached. Note than the request asks permission for one method and the server should return a list of accepted methods. - **Access-Allow-Headers** a list of allowed headers, for all of the methods, since this can be cached as well. - 2. The User-Agent can do the "normal" request. So, if you want to access the `/icecream` resource, and do a PUT there, you'll have the following flow:: > OPTIONS /icecream > Access-Control-Request-Methods = PUT > Origin: notmyidea.org < Access-Control-Allow-Origin = notmyidea.org < Access-Control-Allow-Methods = PUT,GET,DELETE 200 OK You can see that we have an `Origin` Header in the request, as well as a `Access-Control-Request-Methods`. We're here asking if we have the right, as `notmyidea.org`, to do a `PUT` request on `/icecream`. And the server tells us that we can do that, as well as `GET` and `DELETE`. I'll not cover all the details of the CORS specification here, but bear in mind than with CORS, you can control what are the authorized methods, headers, origins, and if the client is allowed to send authentication information or not. A word about security ===================== CORS is not an answer for every cross-domain call you want to do, because you need to control the service you want to call. For instance, if you want to build a feed reader and access the feeds on different domains, you can be pretty much sure that the servers will not implement CORS, so you'll need to write a proxy yourself, to provide this. Secondly, CORS, if misunderstood, can be unsecure, and cause some security problems. Because the rules apply when a client want to do a request to a server, you need to be extra careful about who you're authorizing. A CORS uncorrectly-secured server can be accessed by a client very easily, bypassing the network security. For instance, if a service runs on an intranet, only available from behind a VPN, and accepts every cross-origin call, then anyone service javascript files to the browser of an user with access to this service could make calls there, which is probably not what you want. How this is different from JSONP? ================================= You may know the `JSONP `_ protocol. JSONP Allows to do cross origin, but for a particular use case, and do have some drawbacks (for instance, it's not possible to do DELETEs or PUTs with JSONP. JSONP exploits the fact that's possible to get information from another domain when you are asking for javascript code, using the `