1. Why does CORS exist?
XHR is the Web API that serves as a fundamental API for making requests such as Ajax,… But in its early versions, XHR was limited to the same-origin policy for security reasons.
However, in practice, we do need to handle requests from different origins such as a third-party script that run on a third-party server.
That’s how CORS comes into life.
2. Same/Not-same origin?
The origin is defined as a triple of application protocol, domain name & port number.
Ex: (http, example.com, 80) and (https, example.com, 443) are considered as different origins.
3. CORS handling
When a request is made, the browser will append the protected Origin HTTP header. In turn, the server will then examine the Origin header and decide if it should allow the request by returning an Access-Control-Allow-Origin header in its response.
=> Request
GET /resource.js HTTP/1.1
Host: thirdparty.com
Origin: http://example.com
...
<= Response
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
...
In ExpressJs, we usually use cors() middleware to handle this case.
4. CORS with ‘withCredentials’ header
A simple CORS request usually omit the user credentials such as cookies, HTTP authentication and is limited by the allowed methods.
To enable cookies & HTTP authentication, the client need to set an extra property withCredentials on the XHR request to ask server to respond with the Access-Control-Allow-Credentials = true.
To do that, the client must first ask for permission from the different origin server by issuing a preflight request:
=> Preflight request
OPTIONS /resource.js HTTP/1.1
Host: thirdparty.com
Origin: http://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: My-Custom-Header
...
<= Preflight response
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: My-Custom-Header
...
(actual HTTP request)
The OPTIONS method is used to send a preflight request to the server.
The preflight request can be cached by the client by the browser to avoid the same verification.
Refs:
Book: High Performance Browser Networking | Ilya Grigorik