Apparently, I have completely misunderstood its semantics. I thought of something like this:
http://siteA
- the origin.http://siteB
, which I thought meant that MyCode.js was allowed to make cross-origin references to the site B.http://siteB
, which should be fine, despite being cross-origin requests.Well, I am wrong. It does not work like this at all. So, I have read Cross-origin resource sharing and attempted to read Cross-Origin Resource Sharing in w3c recommendation
One thing is sure - I still do not understand how am I supposed to use this header.
I have full control of both site A and site B. How do I enable the javascript code downloaded from the site A to access resources on the site B using this header?
P.S.
I do not want to utilize JSONP.
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.
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):
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.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-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.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-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.1
Origin: http://siteA.com
Content-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.
But MyCode.js cannot reach for site B in the first place! How will this header arrive at the client? BTW, kudos for the light life glider in the avatar.
I edited with clarification: the browser actually does perform a network fetch on site B to check the
Access-Control-Allow-Origin
header, but it might not provide the response to the JS code on site A if the header doesn't allow site A to have it. (P.S. Thanks :) )Indeed, I do not see any record of the download in Fiddler, unless the cross-origin request is approved. Interesting...
@Jwan622 A fundamental "why?" question like that is probably out of scope for this particular answer, which is just about rules & mechanics. Basically, the browser allows you, the human sitting at the computer, see any resource from any origin. It disallows scripts (which could be written by anyone) from reading resources from origins that are different from the origin of the page running the script. Some related questions are programmers.stackexchange.com/q/216605 and What is the threat model for the same origin policy?
In case of using an authentication,
Access-Control-Allow-Origin
does not accept the*
in some browsers (FF and Chrome AFAIK). So in this case you have to specify the value from theOrigin
header. Hope that this will help someone.