Intended Audience
This article is written by a software developer for anyone who is interested in the technical aspects of modern web browsers. To understand this article, readers need to know the overview of browser's policies. Here is the article on the browser-policies-part-1-technical-overview-of-browser-policies.
Content
- Introduction
- Why we need Same Origin Policy?
- Default behaviour of Same Origin Policy?
- Exclusions from Same Origin Policy?
- How to enable Same Origin Policy?
- How to relax Same Origin Policy?
- Attacks prevented by Same Origin Policy?
- Conclusion
Introduction
Same-Origin-Policy is one of the browser's policies that make browsers a safe place to browse the Internet.
Under this policy browser prevents a script running inside an origin to interact with other origin with some exceptions. We can use an egg crate for an analogy, where each egg represents an origin (browser's tab). Like no two eggs in the crate touches each other in a same way no two origin can interact with each other through a script.
Why we need Same Origin Policy?
Lets assume a normal user's scenario. A user uses a browser for online banking. After doing some stuff, that user forget's to logout and closes the tab. However, user closed that tab, but session is still active at the server.
Now if he/she opens a malicious website which contains a script that makes an api call to the bank's server with all the required session cookies. Bank's server thinks that the real user is making this call and approves the request. Now that malicious website can do whatever it wants. This is scary. Isn't it?
This is the reason browser enforces same origin policy, that no two origin can interact through script any way.
Default behaviour of Same Origin Policy
It is crucial to understand that same-origin-policy applies only to the code written in the script. So by default any attempt to access another origin through code written inside the script is not allowed. However we can load and execute a script from another origin but it should not contain any such code which tries to interact with another origin, otherwise it will throw error.
Cross origin API call
For example a script containing a code to make api to call to another origin, simply throws a CORS error similar to below:
script.js (origin: http://localhost:3001)
fetch('http://localhost:3002/app')
Cross origin document access
Another example to access another origin is through iframes or popup. If we try to access document across origin, it will be null:
script.js (origin: http://localhost:3001)
<iframe id="cross_origin_iframe" src="http://localhost:3002"> </iframe> <script> var cross_origin_iframe = document.getElementById("cross_origin_iframe"); console.log(cross_origin_iframe.document) // null </script>
Same-Origin-Policy applies only to actual script. It does not apply to HTML tags such as <script src="cross_origin_url.js">, <img src="cross_origin_url.png">, <link href="cross_origin_url.css">, etc.
Exclusions from Same Origin Policy
All the HTML tags are excluded from the same origin policy (exception to font). This means that resources are accessed across origins via corresponding HTML tags. Therefore, following cross origin embeddings are allowed:
<script src="cross_origin_url.js"> // Allowed ✅ <img src="cross_origin_url.png"> // Allowed ✅ <link src="cross_origin_url.css"> // Allowed ✅ <iframe src="cross_origin_url.html"> // Allowed ✅ <script src="cross_origin_url.js"> // Allowed ✅ @font-face { font-family: "Open Sans"; src: url("cross_origin_url.woff2"); // Not Allowed ❌ }
Apart from HTML tags, there is one more exclusion from SOP. That is communication instead of accessing. We can communicate with other origins via postMessage or MessageChannel or BroadcastChannel API.
How to enable Same Origin Policy?
There is nothing extra we need to do here, in order to enable SOP. As long as we are on a trusted browser, it is enabled by default by the browser. Therefore any access via script to other origin is simply not allowed.
How to "relax" Same Origin Policy?
We have seen the default behaviour of the SOP. However we can bypass the SOP without "technically" violating the SOP. Therefore the heading mentions "relax" instead of bypass. Following are the ways in we can relax the SOP:
document.domain
The document loaded by an origin contains an interesting property .domain. This property tells what is the domain of the origin. Javascript has access to modify it. If the script in both the origins changes this domain property to a common origin, technically both will be on same origin because the protocol and the port are mostly same for all websites.
// orders.example.com document.domain = example.com // catalog.example.com document.domain = example.comTherefore, cross origin document access is allowed.
Cross-Origin Resource Sharing (CORS)
CORS is most popular and practical way to relax SOP. CORS standard allows controlling SOP via HTTP response (to be set on the server) header: Access-Control-Allow-Origin. This header allows an explicit list of origins, you want to allow interact with your own origin.
// orders.example.com HTTP/1.1 200 OK Server: Apache/2 Access-Control-Allow-Origin: catalog.example.com // catalog.example.com Now we can intereact with orders.example.com from catalog.example.com
Cross-Document Messaging
The two types of cross origin interactions we learned so far Cross origin API call and Cross origin document access in above sections, need follow SOP. There is third type of interaction (communication more precisely) via event messaging does not need to follow SOP. This is because, with this method, the communication is setup through mutual consent between both the origins.
For this, browsers exposes multiple APIs. The most used one is postMessage API. There are other APIs such as MessageChannel and BroadcastChannel API. If you want learn more about cross origin event messaging please read separate articles on the same: postMessage or MessageChannel or BroadcastChannel API.
JSONP (JSON with Padding)
Since, SOP does not apply to HTML elements (Like <script> tags), we usually load scripts from another origins. Like this:
<script src="https://another-origin.com/api"></script>But can we load any data (like .json) through this technique? The answer is NO! Because <script> tag only understands .js files.
JSONP here is the trick to receive .json data. The process is extreamly simple. Intead of sending data in a JSON format, just wrap it around a function call signature.
// Traditional JSON { "roses": "red", "violets": "blue", "grass": "green", } <script src="https://another-origin.com/api"></script> // Browser throws error // JSON-P funtion_name({ "roses": "red", "violets": "blue", "grass": "green", }) <script src="https://another-origin.com/api"></script> // Browser considers it as valid script and executes it.The only requirement is that the origin which is requires this JSONP data must have a pre-defined definition of the funtion "function_name".
WebSockets
The default behaviour of a browser allows any web-socket connection to any origin. Sounds scary, right?
But we have security mechanism in place. Although browsers allows web-scocket connections, they do add an Origin header to the outgoing requests. Now the web-socket server have to validate it against the allowed hosts. In this way we can relax SOP if we want to communicate across origins.
Attacks prevented by Same Origin Policy?
It mitigates threats such as cross-site scripting (XSS). It also prevents malicious website to read data.
Conclusion
Same-Origin-Policy is privacy protection in the world of open Internet connections. If you have appropriate knowledge of methods (we discussed in this article) you can relax this policy as per the need.
Obviously, SOP alone is not sufficient to protect us from the attacks, we need more specialized policies to tackle different attacks. If you want to know about other policies, stay tuned. If you want overview of all the policies please visit browser-policies-part-1-technical-overview-of-browser-policies.
Links & References
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
- https://en.wikipedia.org/wiki/Same-origin_policy
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)
About Author
I love to shape my ideas into a reality. You can find me either working on a project or having a beer with my close friend. :-)