Demystifying Same Origin Policy in Simple Words
Tags: webdev, javascript, beginners, learning
Published: 2024-05-19 07:20:55

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.

![Components of an Origin : Protocol, Host and Port](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja9waklqhvxcp25nsse3.png)

- 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, the most 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**.

![Components of Origin with an Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ih542xgktxo1by073cy.png)

`: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!!!


![Same Origin Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2fob0qaqrwvodsbwsxb.png)

## 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://www.google.com](https://www.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.

![Search engine Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/40qpfmldpvdsrxus516n.png)

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](https://opensource.com/resources/what-emacs#:~:text=Emacs%20is%20a%20text%20editor,it%20for%20nearly%2040%20years.), 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) -

![Disabled by Cross Origin Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7wa2l1lrgg6ulbqx6ma.png)

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.

![Diagrammatic Representation of CORS Mechanism](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7dsn9nvfxmxyalgg7raz.png)
> - image from MDN Web Docs

Let's take a look at this Wikipedia web page on Pikachu-

![Pikachu on Wikipedia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09nlfruvo514cstslngc.png)

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 -
```HTTP
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 -
```HTTP
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
```HTTP
Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin
```
**CORS** header.
**IMPORTANT NOTE:** The policy is only effective for no-cors requests. And most importantly, due to a [bug in Chrome](https://issues.chromium.org/issues/40127935), 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 -
{% embed https://medium.com/@dtkatz/3-ways-to-fix-the-cors-error-and-how-access-control-allow-origin-works-d97d55946d9 %}

## 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. ;)

![Thank You](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ttiizpzt77v1ihokmx5.png)

Have a great day ahead & most importantly -

Happy Coding! 🧑🏻‍💻 👩🏻‍💻