CORS
The text below was previously part of the CORS specification. It was taken out per a suggestion at the May 2012 F2F so it could be maintained by the wider web community.
See also CORS Enabled.
Requirements
- Must not introduce attack vectors to servers that are only protected only by a firewall.
- The solution should not introduce additional attack vectors against services that are protected only by way of firewalls. This requirement addresses "intranet" style services authorize any requests that can be sent to the service.
Note that this requirement does not preclude HEAD
, OPTIONS
, or GET
requests (even with ambient authentication and session information).
- It should not be possible to perform cross-origin non-safe operations, i.e., HTTP operations except for
GET
,HEAD
, andOPTIONS
, without an authorization check being performed. - Should try to prevent dictionary-based, distributed, brute-force attacks that try to get login accounts to 3rd party servers, to the extent possible.
- Should properly enforce security policy in the face of commonly deployed proxy servers sitting between the user agent and any of servers with whom the user agent is communicating.
- Should not allow loading and exposing of resources from 3rd party servers without explicit consent of these servers as such resources can contain sensitive information.
- Must not require content authors or site maintainers to implement new or additional security protections to preserve their existing level of security protection.
- Must be deployable to IIS and Apache without requiring actions by the server administrator in a configuration where the user can upload static files, run serverside scripts (such as PHP, ASP, and CGI), control headers, and control authorization, but only do this for URLs under a given set of subdirectories on the server.
- Must be able to deploy support for cross-origin
GET
requests without having to use server-side scripting (such as PHP, ASP, or CGI) on IIS and Apache. - The solution must be applicable to arbitrary media types. It must be deployable without requiring special packaging of resources, or changes to resources' content.
- It should be possible to configure distinct cross-origin authorization policies for different target resources that reside within the same origin.
- It should be possible to distribute content of any type. Likewise, it should be possible to transmit content of any type to the server if the API in use allows such functionality.
- It should be possible to allow only specific servers, or sets of servers to fetch the resource.
- Must not require that the server filters the entity body of the resource in order to deny cross-origin access to all resources on the server.
- Cross-origin requests should not require API changes other than allowing cross-origin requests. This means that the following examples should work for resources residing on
http://test.example
(modulo changes to the respective specifications to allow cross-origin requests):<?xml-stylesheet type="application/xslt xml" href="http://example.org/annotate.xslt"?>
var client = new XMLHttpRequest()
client.open("GET", "http://example.org/data.text")
client.send()
- It should be possible to issue methods other than
GET
to the server, such asPOST
andDELETE
. - Should be compatible with commonly used HTTP authentication and session management mechanisms. I.e. on an IIS server where authentication and session management is generally done by the server before ASP pages execute this should be doable also for requests coming from cross-origin requests. Same thing applies to PHP on Apache.
- Should reduce the risk of inadvertently allowing access when it is not intended. This is, it should be clear to the content provider when access is granted and when it is not.
Use Cases
The main motivation behind Cross-Origin Resource Sharing (CORS) was to remove the same origin restriction from various APIs so that resources can be shared among different origins (i.e. servers).
XMLHttpRequest
(XHR)
Currently if you have an API on the server at https://calendar.example/add
that accepts requests using the HTTP PUT
method to add new appointments you can only issue such requests from within the browser environment on resources within the https://calendar.example/
origin, as follows:
var client = new XMLHttpRequest()
client.open("PUT", "https://calendar.example/add")
client.onload = requestSuccess
client.onerror = requestError
client.onabort = requestError
client.send(appointment)
If the https://calendar.example/add
resource implements CORS it can accept requests from other origins. To do this the server has to indicate it is willing to handle HTTP PUT
methods for non same-origin requests in response to a preflight request. Further when the actual request is issued it has to indicate it is willing to share any response data.
Code Web application developers use to talk with this resource can however remain unmodified, even when put on another origin.
If there is an API on http://foo.example.org/
that allows authenticated users to edit resources, CORS could be used to allow users to use http://editor.example/
as editor without the need of proxies when communicating changes to resources (e.g. addition or removal).
Not tainting the canvas
element (HTML)
Currently if you have an image editor implemented using the canvas
element at http://unicornimages.example
and a clip art collection at http://narwhalart.example
drawing the clip art on the canvas
element will cause it to be tainted because the images are from a different origin. The effect of a tainted canvas
element is that the toDataURL()
method call in the following snippet will throw:
var canvas, context, clipart = []
function init() {
canvas = document.getElementsByTagName("canvas")[0]
context = canvas.getContext("2d")
}
function preload() {
// populates clipart with five images from
// http://narwhalart.example/archives/[0-9]
// all represented as HTML <img> elements
…
}
function draw(clipart) {
context.drawImage(clipart, …)
}
function save() {
// get data out of <canvas> and process it
var data = canvas.toDataURL()
…
}
Using CORS the maintainer of http://narwhalart.example
can very easily indicate that all images can be used by http://unicornimages.example
(or in fact all origins). To do so all that is required to change is that the server has to add the following HTTP headers for the clip art resources:
access-control-allow-origin: http://unicornimages.example
access-control-allow-credentials: true
This would also make the toDataURL()
method call no longer throw.
Getting metadata out of media elements (HTML)
At some point in the future the HTMLvideo
andaudio
elements will give a programmatic API to access their metadata. This could be as simple as the following snippet shows:
The API itself is pure speculation and its specifics are not relevant for explaining how CORS can be used.
var vid = document.querySelector("video"),
vidAuthor = vid.meta.author
To prevent data theft this API will only work if the media resource is same origin with where the script is executed from. However, if the video were annotated with CORS, similarly to the image resource in the previous use case, this could work just fine.
Server-Sent Events (EVENTSOURCE)
Currently ifhttp://example.org/news
exposes a stream of news events only resources onhttp://example.org
can make use of it. With CORS it would be very easy to allowhttp://international.example.org
to access the stream of news as well. If this news stream is personalized e.g. by the means of cookies it only requires one additional response header forhttp://international.example.org
to be able to make use of it:access-control-allow-origin: http://international.example.org access-control-allow-credentials: true
The code used by Web authors would remain near identical (identical if they use an absolute URL):
stream = EventSource("http://example.org/news")
stream.onmessage = function(e) { … }
xml-stylesheet
processing instruction (XMLSS)
Currently cross-origin loads of XSLT resources are prohibited to prevent data theft (e.g. from an intranet). With CORS an XSLT resourcehttp://static.example.org/generic
can easily be used byhttp://example.org
resources by adding an additional HTTP header to the resource. Again, the code used by Web authors remains the same:<?xml-stylesheet href="http://static.example.org/generic"?>
Design Decision FAQ
Why is there a preflight request?
For most type of requests two resource sharing checks are performed. Initially a "permission to make the request" check is done on the response to the preflight request. And then a "permission to read" check is done on the response to the actual request. Both of these checks need to succeed in order for success to be relayed to the API (e.g. XMLHttpRequest
).
The "permission to make the request" check is performed because deployed servers do not expect such cross-origin requests. E.g., a request using the HTTP DELETE
method. If they reply positively to the preflight request the client knows it can go ahead and perform the actual desired request.
Why is POST
treated similarly to GET
?
Cross-origin POST
requests have long been possible using the HTML form
element. However, this is only the case when Content-Type
is set to one of the media types allowed by HTML forms.
Why can cookies and authentication be included in the request?
Sending cookies and authentication information enables user-specific cross-origin APIs.
Cookies and authentication information is already sent cross-origin for various HTML elements, such as img
, script
, and form
.
Why can cookies and authentication information not be provided by the script author for the request?
This would allow dictionary based, distributed, cookies / user credentials search.
Why is the client the policy enforcement point?
The client already is the policy enforcement point for these requests. The mechanism allows the server to opt-in to let the client expose the data. Something clients currently not do and which servers rely upon.
Note however that the server is in full control. Based on the value of the Origin
header in cross-origin requests it can decide to return no data at all or not provide the necessary handshake (the Access-Control-Allow-Origin
header).
What about the JSONRequest
proposal?
JSONRequest
has been considered by the Web Applications Working Group and the group has concluded that it does not meet the documented [#requirements requirements]. JSONRequest
is a specific API and cannot handle e.g. cross-origin XSLT through <?xml-stylesheet?>
or the same scenarios same-origin XMLHttpRequest
can handle today in cross-origin fashion, e.g. manipulating resources making use of the REST architectural style.