1. Same Origin Policy (SOP)

Before understanding CORS, you first need to know why CORS exists.

What is an Origin?

An Origin is made up of 3 things:

Protocol + Domain + Port

Example:

URL Origin
[https://example.com](https://example.com/) https + example.com + 443
[http://example.com](http://example.com/) http + example.com + 80
[https://api.example.com](https://api.example.com/) https + api.example.com + 443
[https://example.com:3000](https://example.com:3000/) https + example.com + 3000

If any one of these changes, the origin is different.

Example:

https://example.com
https://api.example.com      ❌ Different domain

https://example.com
http://example.com           ❌ Different protocol

https://example.com
https://example.com:3000     ❌ Different port

What is Same Origin Policy?

The Same Origin Policy (SOP) is a browser security policy.

It prevents a webpage from making requests to another origin unless that server explicitly allows it.

Example:

Frontend:

https://myapp.com

Backend:

https://api.myapp.com

Browser:

fetch("https://api.myapp.com/users")

Although both belong to the same company, the origins are different because the domain differs.

The browser blocks the response unless CORS allows it.

Why was SOP introduced?

Imagine you're logged into your bank.

https://mybank.com

Without SOP:

You visit:

https://evil.com

That malicious website secretly executes:

fetch("https://mybank.com/account")

Your browser automatically sends your bank cookies.

Without protection, evil.com could read:

This would be a massive security issue.

So browsers enforce:

"A website can only read responses from the same origin unless the other server explicitly allows it."


Important Point

SOP does NOT stop the request from being sent in every case.

It mainly stops JavaScript from reading the response.

This distinction is important.

2. What is CORS?

CORS stands for:

Cross-Origin Resource Sharing

It is a mechanism that allows servers to tell browsers:

"It's okay. I trust this other origin."

Without CORS:

Frontend
https://myapp.com

↓

Request

↓

https://api.example.com

↓

Browser blocks response

With CORS:

Server sends permission.

Access-Control-Allow-Origin:
https://myapp.com

Now the browser allows JavaScript to read the response.

Example

Frontend:

fetch("https://api.example.com/users")

Server responds:

HTTP/1.1 200 OK

Access-Control-Allow-Origin: https://myapp.com

Browser checks:

Did the server allow my origin?

Yes.

Return response to JavaScript.

3. Access-Control-Allow-Origin

This is the most important CORS header.

Example:

Access-Control-Allow-Origin:
https://myapp.com

Meaning:

Only requests coming from https://myapp.com can access this response.


Allow everyone:

Access-Control-Allow-Origin: *

This means:

Every website is allowed.

Useful for:

Not suitable for authenticated APIs that rely on credentials (cookies or HTTP authentication).

4. Simple Requests

Some requests are considered simple.

Example:

fetch("/users")

or

GET /users

Browser sends the request immediately.

Server responds:

HTTP/1.1 200 OK

Access-Control-Allow-Origin:
https://myapp.com

Browser checks the header.

If allowed:

Response → JavaScript

Otherwise:

Blocked by CORS

5. Preflight Request

Some requests are considered potentially more risky.

Examples:

PUT
DELETE
PATCH

or

Custom headers:

Authorization
X-API-Key

or certain content types such as application/json in many cross-origin scenarios.

Before sending the actual request, the browser first asks:

"Server, are you okay with this type of request?"

This check is called a Preflight Request.

Browser Flow

Suppose JavaScript does:

fetch("/users", {
    method: "DELETE"
})

Browser does NOT send DELETE immediately.

Instead:

OPTIONS /users

This is the preflight request.

Browser asks

OPTIONS /users

Origin:
https://myapp.com

Access-Control-Request-Method:
DELETE

Access-Control-Request-Headers:
Authorization

Meaning:

I want to send a DELETE request with these headers. Is that allowed?


Server replies

HTTP/1.1 204 No Content

Access-Control-Allow-Origin:
https://myapp.com

Access-Control-Allow-Methods:
GET, POST, DELETE

Access-Control-Allow-Headers:
Authorization

Browser checks:

Everything is okay.

Now the browser sends the real request:

DELETE /users

6. Complete Flow

Frontend
    │
    │ DELETE /users
    │
    ▼
Browser
    │
    │ OPTIONS /users
    ▼
Server
    │
    │ Access-Control-Allow-Methods
    │ Access-Control-Allow-Origin
    ▼
Browser
    │
    │ DELETE /users
    ▼
Server
    │
    │ 200 OK
    ▼
Browser
    │
    ▼
JavaScript receives response

Common CORS Headers

Header Purpose
`Access-Control-Allow-Origin` Which origins may access the response
`Access-Control-Allow-Methods` Allowed HTTP methods
`Access-Control-Allow-Headers` Allowed request headers
`Access-Control-Allow-Credentials` Whether credentials like cookies may be sent
`Access-Control-Max-Age` How long the browser can cache a successful preflight response
--- # Interview Questions ### Why do we need CORS? Because browsers enforce the Same Origin Policy.

CORS lets a server explicitly allow trusted cross-origin requests.

Does Postman enforce CORS?

No.

Postman is not a browser, so it does not enforce the Same Origin Policy.

That's why an API can work perfectly in Postman but fail in the browser with a CORS error.

Is CORS a frontend feature or backend feature?

It's a browser security mechanism that relies on the backend to send the appropriate CORS headers.

Who enforces CORS?

The browser.

If the server doesn't send the required headers, the browser blocks JavaScript from accessing the response.

Notion Notes (Short Version)

Same Origin Policy (SOP)

CORS (Cross-Origin Resource Sharing)

Access-Control-Allow-Origin

Preflight Request