CORS Concept - rinku191/AppSec_Topics_for_Interview GitHub Wiki
CORS, or Cross-Origin Resource Sharing, is a mechanism that allows or restricts resources (like fonts, images, APIs) on a web server to be requested from another domain (origin) outside the domain from which the resource originated. It is a key part of web security to prevent malicious behavior while enabling legitimate interactions between domains.
An origin is defined as a combination of:
-
Protocol:
http
orhttps
-
Domain:
example.com
-
Port:
:80
(default for HTTP) or:443
(default for HTTPS), or any custom port.
For example:
-
http://example.com:80
andhttp://example.com:8080
are different origins because the ports are different. -
https://example.com
andhttp://example.com
are different origins because the protocols differ.
The Same-Origin Policy is a security measure implemented in web browsers to prevent a malicious website from accessing resources on another website using JavaScript. It ensures that a web page can only request resources from the same origin it was loaded from.
For example:
- If your web application at
http://app.example.com
tries to fetch data fromhttp://api.example.com
, the browser will block this request by default, as the origins differ.
Sometimes, legitimate applications need to fetch resources across different origins. Examples include:
- A frontend web application hosted on
https://app.example.com
calling an API hosted onhttps://api.example.com
. - Embedding fonts, images, or videos from third-party sources.
- Fetching resources from a content delivery network (CDN).
Without CORS, such cross-origin requests would be blocked due to the Same-Origin Policy.
CORS allows servers to specify who (which origins) can access their resources and which HTTP methods are allowed during a cross-origin request.
CORS works by adding specific HTTP headers in the server's response to inform the browser whether to permit the cross-origin request.
-
Access-Control-Allow-Origin
-
Specifies which origins are allowed to access the resource.
-
Example:
Access-Control-Allow-Origin: https://example.com
-
You can also allow all origins by using a wildcard:
Access-Control-Allow-Origin: *
-
-
Access-Control-Allow-Methods
-
Specifies the HTTP methods allowed when accessing the resource.
-
Example:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
-
-
Access-Control-Allow-Headers
-
Specifies which headers can be used in the request.
-
Example:
Access-Control-Allow-Headers: Content-Type, Authorization
-
-
Access-Control-Allow-Credentials
-
Indicates whether credentials (cookies, authorization headers, etc.) are allowed to be sent with the request.
-
Example:
Access-Control-Allow-Credentials: true
-
-
Access-Control-Expose-Headers
-
Specifies which headers the browser can access from the response.
-
Example:
Access-Control-Expose-Headers: X-Custom-Header
-
-
Access-Control-Max-Age
-
Specifies how long the results of a preflight request can be cached.
-
Example:
Access-Control-Max-Age: 86400
-
A request is considered "simple" if it meets the following criteria:
-
HTTP Methods: Only
GET
,POST
, orHEAD
are used. -
Headers: Only standard headers like
Accept
,Content-Type
(with certain MIME types text/html, form/URLencoded) are used. - No Credentials: Cookies or HTTP authentication are not included.
For simple requests, the browser directly sends the request to the server. The server's response headers determine whether the request is allowed.
If a request does not qualify as "simple," the browser sends a preflight request before the actual request. This preflight request uses the OPTIONS
method to check with the server whether the actual request is allowed.
The server responds to the preflight request with headers like Access-Control-Allow-Origin
, Access-Control-Allow-Methods
, etc. If the preflight check passes, the browser sends the actual request.
Example of a Preflight Request:
OPTIONS /api/data HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
Server Response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type
If your server wants to allow only https://example.com
:
Access-Control-Allow-Origin: https://example.com
If the server wants to allow all origins:
Access-Control-Allow-Origin: *
*
does not allow credentials (cookies) to be sent.
To allow cookies or HTTP authentication to be sent:
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
If a server does not respond with the required CORS headers or if the headers do not match the request, the browser blocks the request. Some common errors include:
-
CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
- The server did not include the
Access-Control-Allow-Origin
header in the response.
- The server did not include the
-
CORS policy: The origin is not allowed.
- The
Access-Control-Allow-Origin
header does not match the requesting origin.
- The
const express = require('express');
const cors = require('cors');
const app = express();
// Allow specific origin
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
}));
app.get('/api/data', (req, res) => {
res.json({ message: 'CORS is working!' });
});
app.listen(3000, () => console.log('Server running on port 3000'));
fetch('https://api.example.com/data', {
method: 'GET',
credentials: 'include', // Include cookies
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Pre-plight Request table
- CORS is browser-enforced; it does not affect server-to-server communication.
- Incorrect CORS settings can expose your server to security risks (e.g., data theft).
- If Access-Control-Allow-Credentials: true but the Cookie is set samesite=strict can't send cookie value to the Server
- Always use CORS configurations tailored to your application's requirements.