Know The Web: SOP (Same Origin Policy)
Tags: webdev, security, cybersecurity, codenewbie
Published: 2021-02-22 19:29:14

Hey folks! in this post we'll learn about **SOP (Same Origin Policy)**.

Before understanding what SOP is and why we need it, let's ask a question

## What will happens if

If I try to access or modify an `iframe` contents using JS? Let's find out,
```html
<body>
<iframe name="my_frame" src="http://google.com/webhp?igu=1"></iframe>
</body>
```
and open it in your browser. Now head over to the dev tools console and try accessing it using JS like so:

```js
frames.my_name.document
```
Boom! we go an error:

>VM1678:1 Uncaught DOMException: Blocked a frame with origin "null" from accessing a **cross-origin** frame.
    at <anonymous>:1:17

notice, it says **blocked frame from accessing cross-origin frame** i.e since the origin inside the iframe and the origin of our website doesn't match the browser won't allow us to access the iframe contents.

## Same Origin Policy

MDN Docs says:

> The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.

Okay so what they say is pretty clear but what is **origin**? How do we know whether two origins are the same or not?

![questions](https://media.giphy.com/media/8lQyyys3SGBoUUxrUp/giphy.gif)

**Origin** is the combination of **protocols**/**scheme**, **hostname** and **port** number.

![origin without port number](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/125yvwl66auujz8e27cc.png)

OR

![origin with a port number](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txl84vjn0riseln4tkxf.png)

now, not to get confused with URL and origin, both are different. Head over to `http://example.com/abc/def`. Now in the console do the following:  

![difference between URL and Origin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsy11b0ijzg1ny0ndkdk.png)

it's difficult to draw curly brackets 😅 but now you can see the difference between URL and Origin.

Here is an example to understand same-origin and cross-origin

|origin-1|origin-2|cross-origin or same-origin|
|--------|--------|---------------------------|
|http://example.com:80/|http://example.com/| same-origin as 80 is default port number for http|
||http://example.com:80/|same-origin as a port, protocol, and hostname are same|
||https://example.co:80/| cross-origin as the protocol differs. Origin-1 has **http** and origin-2 has **https**|
||http://www.example.com:80/| cross-origin as origin-2 is subdomain(www)|
||http://example.net:80/| cross-origin as the top-level domain(.com,.net) in hostname do not match|

from the above table, we can conclude that for two origins to be the same their **protocols**,**hostname**, and **port number**(if mentioned) have to be the same. Try testing the above examples using `location.href` and `location.origin` in the browser console.

We can explain why we were unable to access the content inside `iframe` in the very first question we asked. As the origin of our webpage and that of the website inside the iframe were different. Let's try to access iframe contents when the origin is same, here is a simple node js server:

```js
//index.js
const app=require('express')();
const path=require('path');

app.get('/',(req,res)=>{
   res.sendFile(path.join(__dirname+'/main.html'));
});

app.get("/abc",(req,res)=>{
    res.send("Hi! I am inside iframe.");
});

app.listen(8080,(err)=>{
   if(err) console.log(err);
   console.log(">8080<");
});
```
and 
```html
<!--main.html-->
<body>
    <h1>Hi! I contain an iframe</h1>
    <iframe name="my_local_frame" src="/abc"></iframe>
</body>
```

after running, head over to `http://localhost:8080`. we access the iframe content and boom! we get no error. 

![can access iframe content with same origin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gj1e1yq7g5xevs68igev.png)

if we check origin:

![origin outside iframe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ijj8sxvrf14jbfz1sl73.png)

![origin of iframe content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x0lqp95iyqcoqptz1fc5.png)

Okay, so things are pretty clear now. You may ask, how webpages are able to load external scripts and resources from CDNs, their origin does not match. It should rather block them.

Why would it block it?

SOP's purpose is not to block the dynamic loading of scripts, but to prevent a script from one site to access the data of another site.

## Security

Suppose, Same-Origin Policy didn't exist.

Let's say you visit `target.com`, you log in, you get a valid session cookie & then you leave without logging out.

Next, you visit `evil.com` which tries to impersonate you & send an evil request to `target.com`(from your browser). Since you never logged out & you still have a valid session cookie (which follows every request your browser makes to `target.com`), the target will recognize your browser & (may) accept the evil request. This is called [Cross-Site Request Forgery (CSRF)](https://portswigger.net/web-security/csrf). Using this attack, the attacker can access your personal details or may end up changing your account credentials and you are no longer able to log in.

This is where SOP comes into play. 
Although the evil request won't be blocked by your browser (it's up to `target.com` to protect itself against **CSRF** attacks), the response won't be made available to `evil.com`.
So even if `target.com` is **misconfigured** & falls for a CSRF attack that requests your personal info, for example, SOP won't allow `evil.com` to see that info. 

That's what SOP does and that's all for this post. Feel free to suggest improvements and point out any mistakes :)