CORS — Cross-Origin Requests
BookNook's website lives at https://booknook.example, and its API at https://api.booknook.example. The first time the website's JavaScript calls the API, the browser console fills with red: "blocked by CORS policy". The API is working. The browser is protecting users, and your API has to tell it this caller is welcome.
The rule
The browser asks; the server's headers grant; nobody else enforces it.
An origin is the combination of scheme, host and port. https://booknook.example and https://api.booknook.example differ in host, so they are different origins. By default, browsers stop page JavaScript from reading responses from another origin. This same-origin policy keeps a malicious site from reading your bank data with your cookies.
CORS (Cross-Origin Resource Sharing) is how a server relaxes that rule for chosen origins. The browser adds an Origin header; the server answers with permission headers:
GET /v1/books HTTP/1.1
Origin: https://booknook.example
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://booknook.exampleFor anything beyond a basic request (a method other than GET, HEAD or POST, a body type such as application/json, or extra headers like Authorization), the browser first sends a preflight, an automatic OPTIONS request that asks permission:
OPTIONS /v1/loans/901 HTTP/1.1
Origin: https://booknook.example
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: authorization
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://booknook.example
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Max-Age: 600Only if the preflight grants permission does the browser send the real DELETE. Access-Control-Max-Age lets it remember the answer for 10 minutes.
To send cookies across origins, the server must also reply Access-Control-Allow-Credentials: true, and then Access-Control-Allow-Origin must name the exact origin; the wildcard * is not accepted.
The shortcut
Diagnose a CORS error in three checks: Is it a browser? Are the origins different? Do the response headers grant this origin, method and headers?
Is it a browser?
Yes, page JavaScript. The same call from a server or
curlwould work, because CORS is only enforced by browsers.
The trap is thinking CORS protects your API. It does not stop curl or a server calling you; it only stops other websites' pages from reading responses in a user's browser. Your API still needs real authentication.
Drills
Answer fast — trust the rule.
Which pair has the SAME origin?
Who enforces CORS?
The website sends a PATCH with Content-Type: application/json. What does the browser do first?
The API replies Access-Control-Allow-Origin: * and the site sends cookies with its requests. What happens?
A teammate says "we set strict CORS, so attackers cannot call our API". What is wrong?
Remember
- The browser asks; the server's headers grant; nobody else enforces it.
- Shortcut: is it a browser, are the origins different, do the headers grant it?
- Trap: treating CORS as security for your API, and
*with credentials.
