How does Access-Control-Allow-Origin header work? How does Access-Control-Allow-Origin header work? javascript javascript

How does Access-Control-Allow-Origin header work?


Access-Control-Allow-Origin is a CORS (Cross-Origin Resource Sharing) header.

When Site A tries to fetch content from Site B, Site B can send an Access-Control-Allow-Origin response header to tell the browser that the content of this page is accessible to certain origins. (An origin is a domain, plus a scheme and port number.) By default, Site B's pages are not accessible to any other origin; using the Access-Control-Allow-Origin header opens a door for cross-origin access by specific requesting origins.

For each resource/page that Site B wants to make accessible to Site A, Site B should serve its pages with the response header:

Access-Control-Allow-Origin: http://siteA.com

Modern browsers will not block cross-domain requests outright. If Site A requests a page from Site B, the browser will actually fetch the requested page on the network level and check if the response headers list Site A as a permitted requester domain. If Site B has not indicated that Site A is allowed to access this page, the browser will trigger the XMLHttpRequest's error event and deny the response data to the requesting JavaScript code.

Non-simple requests

What happens on the network level can be slightly more complex than explained above. If the request is a "non-simple" request, the browser first sends a data-less "preflight" OPTIONS request, to verify that the server will accept the request. A request is non-simple when either (or both):

  • using an HTTP verb other than GET or POST (e.g. PUT, DELETE)
  • using non-simple request headers; the only simple requests headers are:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (this is only simple when its value is application/x-www-form-urlencoded, multipart/form-data, or text/plain)

If the server responds to the OPTIONS preflight with appropriate response headers (Access-Control-Allow-Headers for non-simple headers, Access-Control-Allow-Methods for non-simple verbs) that match the non-simple verb and/or non-simple headers, then the browser sends the actual request.

Supposing that Site A wants to send a PUT request for /somePage, with a non-simple Content-Type value of application/json, the browser would first send a preflight request:

OPTIONS /somePage HTTP/1.1Origin: http://siteA.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: Content-Type

Note that Access-Control-Request-Method and Access-Control-Request-Headers are added by the browser automatically; you do not need to add them. This OPTIONS preflight gets the successful response headers:

Access-Control-Allow-Origin: http://siteA.comAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: Content-Type

When sending the actual request (after preflight is done), the behavior is identical to how a simple request is handled. In other words, a non-simple request whose preflight is successful is treated the same as a simple request (i.e., the server must still send Access-Control-Allow-Origin again for the actual response).

The browsers sends the actual request:

PUT /somePage HTTP/1.1Origin: http://siteA.comContent-Type: application/json{ "myRequestContent": "JSON is so great" }

And the server sends back an Access-Control-Allow-Origin, just as it would for a simple request:

Access-Control-Allow-Origin: http://siteA.com

See Understanding XMLHttpRequest over CORS for a little more information about non-simple requests.


Cross-Origin Resource Sharing - CORS (A.K.A. Cross-Domain AJAX request) is an issue that most web developers might encounter, according to Same-Origin-Policy, browsers restrict client JavaScript in a security sandbox, usually JS cannot directly communicate with a remote server from a different domain. In the past developers created many tricky ways to achieve Cross-Domain resource request, most commonly using ways are:

  1. Use Flash/Silverlight or server side as a "proxy" to communicatewith remote.
  2. JSON With Padding (JSONP).
  3. Embeds remote server in an iframe and communicate through fragment or window.name, refer here.

Those tricky ways have more or less some issues, for example JSONP might result in security hole if developers simply "eval" it, and #3 above, although it works, both domains should build strict contract between each other, it neither flexible nor elegant IMHO:)

W3C had introduced Cross-Origin Resource Sharing (CORS) as a standard solution to provide a safe, flexible and a recommended standard way to solve this issue.

The Mechanism

From a high level we can simply deem CORS is a contract between client AJAX call from domain A and a page hosted on domain B, a typical Cross-Origin request/response would be:

DomainA AJAX request headers

Host DomainB.comUser-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/jsonAccept-Language en-us;Accept-Encoding gzip, deflateKeep-Alive 115Origin http://DomainA.com 

DomainB response headers

Cache-Control privateContent-Type application/json; charset=utf-8Access-Control-Allow-Origin DomainA.comContent-Length 87Proxy-Connection Keep-AliveConnection Keep-Alive

The blue parts I marked above were the kernal facts, "Origin" request header "indicates where the cross-origin request or preflight request originates from", the "Access-Control-Allow-Origin" response header indicates this page allows remote request from DomainA (if the value is * indicate allows remote requests from any domain).

As I mentioned above, W3 recommended browser to implement a "preflight request" before submiting the actually Cross-Origin HTTP request, in a nutshell it is an HTTP OPTIONS request:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

If foo.aspx supports OPTIONS HTTP verb, it might return response like below:

HTTP/1.1 200 OKDate: Wed, 01 Mar 2011 15:38:19 GMTAccess-Control-Allow-Origin: http://DomainA.comAccess-Control-Allow-Methods: POST, GET, OPTIONS, HEADAccess-Control-Allow-Headers: X-Requested-WithAccess-Control-Max-Age: 1728000Connection: Keep-AliveContent-Type: application/json

Only if the response contains "Access-Control-Allow-Origin" AND its value is "*" or contain the domain who submitted the CORS request, by satisfying this mandtory condition browser will submit the actual Cross-Domain request, and cache the result in "Preflight-Result-Cache".

I blogged about CORS three years ago: AJAX Cross-Origin HTTP request


Question is a bit too old to answer, but I am posting this for any future reference to this question.

According to this Mozilla Developer Network article,

A resource makes a cross-origin HTTP request when it requests a resource from a different domain, or port than the one which the first resource itself serves.

enter image description here

An HTML page served from http://domain-a.com makes an <img> src request for http://domain-b.com/image.jpg.
Many pages on the web today load resources like CSS stylesheets, images and scripts from separate domains (thus it should be cool).

Same-Origin Policy

For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts.
For example, XMLHttpRequest and Fetch follow the same-origin policy.
So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.

Cross-Origin Resource Sharing (CORS)

To improve web applications, developers asked browser vendors to allow cross-domain requests.

The Cross-Origin Resource Sharing (CORS) mechanism gives web servers cross-domain access controls, which enable secure cross-domain data transfers.
Modern browsers use CORS in an API container - such as XMLHttpRequest or Fetch - to mitigate risks of cross-origin HTTP requests.

How CORS works (Access-Control-Allow-Origin header)

Wikipedia:

The CORS standard describes new HTTP headers which provide browsers and servers a way to request remote URLs only when they have permission.

Although some validation and authorization can be performed by the server, it is generally the browser's responsibility to support these headers and honor the restrictions they impose.

Example

  1. The browser sends the OPTIONS request with an Origin HTTP header.

    The value of this header is the domain that served the parent page. When a page from http://www.example.com attempts to access a user's data in service.example.com, the following request header would be sent to service.example.com:

    Origin: http://www.example.com

  2. The server at service.example.com may respond with:

    • An Access-Control-Allow-Origin (ACAO) header in its response indicating which origin sites are allowed.
      For example:

      Access-Control-Allow-Origin: http://www.example.com

    • An error page if the server does not allow the cross-origin request

    • An Access-Control-Allow-Origin (ACAO) header with a wildcard that allows all domains:

      Access-Control-Allow-Origin: *