Table of Contents
- The Same-Origin Policy Problem π
- Enter CORS: The Security Guard π
- Common CORS Headers Explained π
- Quick Node.js/Express Implementation π οΈ
- Common CORS Gotchas π―
- Best Practices π
- Conclusion π¬
CORS (Cross-Origin Resource Sharing) is often misunderstood as just another security headache for developers. Let's break down what it actually does and why it's crucial for web security.
The Same-Origin Policy Problem π
Imagine you're at app1.com
and your JavaScript code tries to fetch data from app2.com
. Without CORS, this request would be blocked by the browser's same-origin policy. This policy prevents a malicious website from reading sensitive data from another website - like your banking details or private messages.
Enter CORS: The Security Guard π
CORS acts like a security guard that allows controlled access between different domains. Here's how it works:
- The Request: Your frontend code makes a request to a different domain:
// Frontend at app1.com
fetch('http://api.app2.com/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
});
- The Preflight: For certain requests, the browser first sends an OPTIONS request to check if the actual request is allowed:
OPTIONS /data HTTP/1.1
Host: api.app2.com
Origin: https://app1.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Content-Type
- The Permission: The server responds with what's allowed:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app1.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Common CORS Headers Explained π
-
Access-Control-Allow-Origin
: Who can access the resource-
*
means everyone (use cautiouslyβΌοΈ) -
https://app1.com
means only that specific domain
-
-
Access-Control-Allow-Methods
: Allowed HTTP methods- Example:
GET, POST, PUT, DELETE
- Example:
-
Access-Control-Allow-Headers
: Allowed request headers- Example:
Content-Type, Authorization
- Example:
-
Access-Control-Max-Age
: How long to cache preflight results- Example:
86400
(24 hours)
- Example:
Quick Node.js/Express Implementation π οΈ
Here's how to implement CORS in a Node.js/Express server:
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://app1.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// Handle preflight
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
// Or use the cors package
const cors = require('cors');
app.use(cors({
origin: 'https://app1.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
Common CORS Gotchas π―
- Credentials: If you're sending cookies or auth headers, you need:
// Frontend
fetch(url, {
credentials: 'include'
});
// Backend
res.header('Access-Control-Allow-Credentials', 'true');
-
Wildcard Limitations: You can't use
*
with credentials
// This won't work with credentials
res.header('Access-Control-Allow-Origin', '*');
// Use specific origins instead
res.header('Access-Control-Allow-Origin', 'https://app1.com');
Best Practices π
-
Be Specific: Avoid using
*
forAccess-Control-Allow-Origin
- Limit Methods: Only allow necessary HTTP methods
-
Cache Preflights: Set appropriate
Access-Control-Max-Age
- Secure Credentials: Be extra careful when allowing credentials
- Validate Origins: Maintain a whitelist of allowed domains
Conclusion π¬
CORS isn't just a barrier - it's a crucial security feature that protects users while enabling controlled cross-origin communication. Understanding how it works helps you implement it correctly and debug issues more effectively.
Remember: CORS is enforced by browsers, not servers. Server-to-server communication doesn't use CORS, so make sure to implement proper security measures for those scenarios.