CORS for Web Developer
Introduction
Recently, while dealing with some cybersecurity issues, I found that my knowledge in this area was quite lacking. As a front-end engineer, cybersecurity is usually not a primary focus, but the consequences of vulnerabilities can be disastrous. Therefore, I have been trying to fill in my knowledge gaps in this area.
What is CORS
CORS (Cross-Origin Resource Sharing) is a mechanism that determines whether a web page can access resources from other origins.
Before discussing CORS, it’s essential to understand the browser’s Same-Origin Policy, which is a security mechanism that restricts interactions between web pages from different origins. A web page’s origin can be defined by three parts:
- Protocol:
http
,https
- Host:
www.example.com
- Port:
80
,443
Only when all three parts are the same will the browser consider it the same origin; otherwise, it is cross-origin. CORS is the protective measure provided by the browser to determine whether to allow cross-origin requests. This setting usually needs to be adjusted on the server side regarding CORS configurations.
CORS Configuration
CORS settings are made on the server side by configuring HTTP headers to inform the browser whether to allow cross-origin requests. Specifically, the browser categorizes requests into two types:
Simple Requests
- Can only be
GET
,POST
, orHEAD
methods - Custom headers can only be
Accept
,Accept-Language
,Content-Language
, orContent-Type
(values can only beapplication/x-www-form-urlencoded
,multipart/form-data
, ortext/plain
) according to Fetch Spec - The object making the request does not have registered event listeners
- No
ReadableStream
objects are used for uploads in the request
In simple requests, the header will include Origin
to inform the server of the request’s origin.
GET /doc HTTP/1.1Origin: Server-b.com
The server will decide whether to allow cross-origin requests based on this origin. If allowed, the server will include Access-Control-Allow-Origin
in the response to inform the browser that this origin is permitted.
HTTP/1.1 200 OKAccess-Control-Allow-Origin: *
Non-Simple Requests
It was previously mentioned that this is a browser mechanism to block non-same-origin requests. Specifically, some requests, such as POST
, PUT
, DELETE
(or any non-simple requests), can change the server’s state just by being sent. Therefore, it is not possible to simply retrieve the request and then decide whether to block it. Instead, these requests will go through a preflight request, which means sending an OPTIONS
request in advance to ask the server whether the operation is allowed:
OPTIONS /doc HTTP/1.1Origin: http://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHER, Content-Type
Then the server responds to allow the request:
HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400
After confirming that the non-simple request can be accepted, the browser will actually send the request:
POST /doc HTTP/1.1X-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Origin: http://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHER, Content-Type
And the server responds with the allowed origin:
HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://foo.example
Summary
CORS is an essential security mechanism in modern web applications that effectively prevents unauthorized resource access between different origins. Through CORS, legitimate cross-origin requests can be allowed while protecting user data.
Further Reading
- Same-origin policy - mdn
- CORS in 100 Seconds - Fireship
- I Hate CORS. - Theo - t3.gg
- Introduction to Cross-Origin Resource Sharing (CORS) - Li Jia Jun