Demystifying Same Origin Policy in Simple Words
According to MDN Web Docs, -
The same-origin policy is a critical security mechanism that restricts how a document or script loaded by one origin can interact with a resource from another origin.
If you are a web developer or someone learning node.js (I mean backend development in JavaScript), 'Same-Origin Policy' is a very important concept to learn because it is definitely going to come up in your career any time.
Hold on your curiosity and bear with me to properly understand this often-misunderstood concept.
First let's make sure we all know what an origin is.
So, without wasting further time, let's dive in!
What Exactly is an Origin?
When we go to a website like google drive when browsing the Web, what we type in the browser is something like, - https://www.google.com/drive.
Similarly, when we open GitHub to manage our web hosted, source-controlled projects, we type something like https://github.com/dashboard in our browser.
And an origin is a combination of 3 things you can see here.
The first is the Protocol => which is the part that says how you are connecting to or say, communicating with the server at Google or GitHub. In this case, we are using the http secure protocol.
Next up, we have a critical part of the origin => which is the Host. The host tells us which server we're going to be browsing to or which server is going to be handling our requests.
And the third part of the origin is the => Port.
:443
is the port that our browser always assumes when we are using the http secure protocol (https).
Whenever any of the 3 components change, we are no longer in the same origin. We can browse to other pages at that origin, so maybe you replace dashboard with your GitHub username to get your GitHub profile.
But we can't really change github.com to wikipedia.org or google.com or say, twitter.com and still be at the same origin.
If we change the protocol (like http not https), our origin will still be changed.
An origin is a combination of these three things, - protocol, host & port and each of the component matters.
I hope my explanation makes a lot of sense.
At this point of reading, you might be thinking, "Why I need to know about this? Why even any of these things matter to us?".
It matters because our browsers and JavaScript follows a rule called the 'Same Origin Policy'.
Exploring Same Origin Policy
In simple language, 'Same Origin Policy' is a special security feature by browsers that prevents one origin from requesting resources from other origin on the client.
For example, - suppose you are browsing a page on www.wikipedia.org and try to fetch some data from a different origin, like www.google.com. Your Browser will abort the request.
Same Origin Policy allows us to load data from the only same origin we are currently browsing. Means, while you are browsing google.com, you can only make requests to pages of google.com, requests to facebook.com or any other origin is not allowed.
Why this feature exists?
Same Origin Policy helps us to protect our privacy. How? Suppose you were browsing a webpage on google.com and made a GET request on facebook.com. If same origin policy didn't exist, as at that time you were browsing google.com, it could possibly collect your data you were fetching from facebook.com. How horrible!!!
Does Same Origin Policy Apply in All Possible Scenarios?
No. While cross origin GET requests are denied, POST requests are allowed. They are allowed simply because they don't risk your data to be leaked from one origin to another. For example, - if you are sending a POST request from https://google.com to https://facebook.com, then if google.com can write or send anything to facebook.com, it's completely up to the Facebook server that how it will respond to the request.
Also, if you search emacs on google search engine, you will get to see a similar result like below.
At this point you are actually browsing, google.com and if you click on the link shown in the image - What is Emacs? - Opensource.com, you won't be restricted to visit the page because you weren't sending any request with JavaScript but clicked the link in a html. So here Same Origin Policy doesn't apply to you.
But instead, if you open the browser console, and use the built-in fetch API function present in the global window object, like this (shown below) -
You'll receive this error.
You can clearly see that our promise is rejected and 'Access to fetch has been blocked by CORS policy'.
Now you might be thinking, what the heck is this CORS policy? Huh!
Diving into CORS policy
CORS stands for Cross Origin Resource Sharing.
- image from MDN Web Docs
Let's take a look at this Wikipedia web page on Pikachu-
If you are browsing this Wikipedia page, to follow along with me -
Open the developer tools, and refresh the page,
Open the Network Tab,
Click on headers.
On the left-hand side, in the name column, at the very topmost point you'll find the item getting the first request, which is the main article, showing the data that we see in front of us.
Now if you click on any image of Pikachu in the Name column & look at the headers tab, you can see the image belongs to a different domain which is www.wikimedia.org. Wikimedia is a partner website of Wikipedia from where Wikipedia collects its necessary media contents.
Scroll down & see in the Response Headers option, here --> Access-Control-Allow-Origin
is set as *
(wildcard).
The Access-Control-Allow-Origin
response header indicates whether the response can be shared with requesting code from the given origin. Setting -
Access-Control-Allow-Origin: *
enables any origin on the internet to access/fetch data from the server. This is the most common option for websites that are under development or are really meant to be used by literally everyone on the internet.
Similarly -
Access-Control-Allow-Origin: https://example.com
will let the origin - https://example.com
(as well as its own origin) to access the any data on the server.
NOTE: Only one origin can be specified as value.
This Access-Control-Allow-Origin
CORS header is entirely optional, if you have a server and don't want any origin to fetch any resource from your server, just don't specify anything, don't include it. We always have our first option of NOT to include it & keep the textbook same origin policy.
If we don't set this Access-control-Allow-Origin
header, the default rules of the same origin policy apply, and it's only really your own domain, which can talk to your server and get any data from it.
But that's just not the most common situation.
When, like Wikipedia and the Wikimedia Foundation, you have your content on many different origins, or you have many different APIs at different sites. This CORS header allows us as developers to allow an exception when we know requests from a different domain are safe and expected. This header is always set on the response & controlled by the server who owns the data.
Wikimedia Foundation decided that access to their data is more important than securing it. Which makes sense when you're hosting publicly available data.
This is how we apply CORS (Cross Origin Resource Sharing) on our websites.
The main reason that Access-control-Allow-Origin
is so secure, is because it follows the practice of whitelisting (the opposite of blacklisting). Whitelisting is when you only specify a list of privileges to allow and rest of them (every other one) are blocked.
The Real reason behind why our original request from Google and our JavaScript console failed while browsing our Google search results, is that the original request to the article or even to the Wikipedia homepage doesn't have any CORS headers. There's no access control.
For adding an extra layer of security, if desired, one can add the -
Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin
CORS header.
no-cors
requests. And most importantly, due to a bug in Chrome, setting Cross-Origin-Resource-Policy can break PDF rendering, preventing visitors from being able to read past the first page of some PDFs. Exercise caution using this header in a production environment.- According to MDN Web Docs
If you're struggling with problems created with CORS or want to learn more - I would like to refer this medium article written by David Katz to you -
Conclusion
We really learnt a lot about origins and the 'same-origin-policy' in this article. I hope you found this blog valuable and from now on you will understand and easily take action on any CORS error you possibly stumble into in future.
Please like ๐ & share ๐ค my blog if you found it useful....
If you learned something new, please consider sharing it with others on Twitter and tag me in your post so I can see it too. ;)
Have a great day ahead & most importantly -
Happy Coding! ๐ง๐ปโ๐ป ๐ฉ๐ปโ๐ป
Subscribe to my newsletter
Read articles from Debajyati Dey directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Debajyati Dey
Debajyati Dey
Linux Enthusiast, Terminal Nerd, interested in open source, web dev, Neovim BTW