Same origin policy
According to Wikipedia, the same origin policy is:
In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. An origin is defined as a combination of URI scheme, hostname, and port number. This policy prevents a malicious script on one page from obtaining access to sensitive data on another web page through that page’s Document Object Model.
In short, the same origin policy is not a technical limitation but an artificial one implemented to protect the user. As this is a good for the overall security of the web, all major browsers implement the same origin policy.
Breaking the same origin policy with CORS
While the same origin policy is a good concept, there are legit cases when developers would like to implement so-called cross origin XMLHttpRequests to directly communicate with a server that is not the one where the HTML page came from.
This is why the CORS (Cross-origin resource sharing) specification was created. According to Wikipedia, CORS is:
A web page may freely embed images, style sheets, scripts, iframes, videos and some plugin content (such as Adobe Flash) from any other domain. However embedded web fonts and AJAX (XMLHttpRequest) requests have traditionally been limited to accessing the same domain as the parent web page (as per the same-origin security policy). “Cross-domain” AJAX requests are forbidden by default because of their ability to perform advanced requests (POST, PUT, DELETE and other types of HTTP requests, along with specifying custom HTTP headers) that introduce many security issues as described in cross-site scripting.
CORS defines a way in which a browser and server can interact to safely determine whether or not to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests, but is more secure than simply allowing all cross-origin requests. It is a recommended standard of the W3C.
How does CORS work?
CORS uses special HTTP headers to define which cross-domain calls are explicitly allowed.
The client adds a request header “Origin” to specify the origin of the HTML page which tries to do the cross-origin call:
The server adds a response header “Access-Control-Allow-Origin” to specify from which origins it accepts cross-origin calls:
To specify that the server allows calls from all origins you can also use “*” as origin:
Preflight for more complex cases
The simple case shown above only applies for specific cases with some limitations:
- The HTTP method must be
- Only standard HTTP headers are allowed to be sent by the browser
POSTrequests, only content types
In other cases, a so-called “preflighted request” is necessary. To do this, the browser will transparently send an additional request with method
OPTIONS before sending the actual request. With the
OPTIONS request, the browser and server exchange information about permissions regarding cross origin requests. In addition, the server defines how long the browser is allowed to cache this information to save additional
OPTIONS request for further requests.
This special request contains the following information:
OPTIONS /some/path HTTP/1.1
Origin: Origin: http://www.oio.de
The matching response looks like this:
Access-Control-Allow-Methods: POST, GET, OPTIONS
Cookies and authentication methods
To transmit cookies or support authentication (e.g. basic authentication), adjustments on both sides, client and server, are necessary.
On the client side, the field
withCredentials of the
XMLHttpRequest needs to be set to
true to make the browser send cookies and handle authentication requirements from the server.
On the server side the header
Access-Control-Allow-Credentials must be added to the response:
Standardization and browser support
The CORS specification is in the state of a recommendation since 2014. Speaking of browser support, all major browsers provide implementations of CORS in their latest versions. As daily business isn’t so easy, it is a little bit more difficult:
Let’s have a look at the compatibility list at caniuse.com:
- Current versions of Google Chrome/Firefox/Firefox ESR/Opera/IE have full support for CORS
- To use CORS in IE8/9, you have to use a proprietary XDomainRequest instead of XMLHttpRequest which has some limitations
- Current versions of Safari (Mac/iOS) and older but commonly used versions of Android have some limitations that do not affect XMLHttpRequest
- Opera Mini doesn’t support CORS at all
So from a business view where Opera Mini isn’t very relevant: If you do not need to support IE versions before IE 10, you are totally safe. If you need to support IE 8/9 you need to adapt XDomainRequest on these browsers or you can use a polyfill for this.