Part II β The Shield Β· Lesson 3.14
Cross-Origin Resource Sharing (CORS)
In one lineThe browser blocks cross-origin reads by default; CORS is the server's way of granting an exception.
Where you've seen itapp.example.com fetching from api.example.com. Same company, same certificate, still a different origin.
Diagram
WHAT COUNTS AS THE SAME ORIGIN β all three must match
https://app.example.com:443/users
βββ¬βββ ββββββββ¬βββββββββ ββ¬β
scheme host port
vs https://app.example.com/orders β same origin
vs http://app.example.com β scheme differs
vs https://api.example.com β host differs
vs https://app.example.com:8443 β port differsPREFLIGHT β asked before anything that isn't "simple"
Browser Server
βββ OPTIONS /orders βββββββββββββββΊβ
β Origin: https://app.example.comβ
β Access-Control-Request-Method: DELETE
β Access-Control-Request-Headers: authorization
β β
βββ 204 ββββββββββββββββββββββββββββ
β Access-Control-Allow-Origin: https://app.example.com
β Access-Control-Allow-Methods: GET, POST, DELETE
β Access-Control-Allow-Headers: authorization
β Access-Control-Max-Age: 86400 β cache the preflight
β β
βββ DELETE /orders/9 ββββββββββββββΊβ the real request, now allowedSIMPLE REQUEST β no preflight
method GET Β· HEAD Β· POST
headers only Accept, Accept-Language, Content-Language, Content-Type
type Content-Type β {text/plain, multipart/form-data,
application/x-www-form-urlencoded}
application/json β NOT simple β preflight. This is why almost
every real API call triggers an OPTIONS first.How it works
- The browser attaches
Originto cross-origin requests. - For non-simple requests it sends an
OPTIONSpreflight first and waits for permission. - The server responds with
Access-Control-Allow-*headers; the browser enforces them. - The request usually still reaches the server β CORS blocks the response from being read by JS. It is not server-side access control.
- For cookies, the client sets
credentials: 'include'and the server must sendAccess-Control-Allow-Credentials: truewith an explicit origin β*is rejected in that combination.
Trade-offs
| Setting | Consequence |
|---|---|
Allow-Origin: * | Public read-only APIs only; no credentials |
Echoing the Origin header back | Equivalent to * unless you validate against an allowlist |
Max-Age: 86400 | Removes a preflight round trip per session |
| Same-origin via reverse proxy | No CORS at all β often the simplest fix |
Interview angle
"You get a CORS error. Is it a frontend bug?"
- No β CORS is granted by the server, so the fix is a response header, not client code.
- Read the exact message: disallowed origin, disallowed header, or missing credentials support each need a different header.
- The clean production answer is often to remove the cross-origin call entirely by proxying the API under the same origin.
Recap
- Same origin = scheme + host + port, all three.
- Non-simple requests (including any JSON body) pay a preflight; cache it with
Max-Age. - CORS protects the user's data from other sites β it never protects your API from a direct client.