Knowledge Base
CORS Header Selection Cheatsheet
guide networking||8 min read|
Share
A quick reference guide for configuring Cross-Origin Resource Sharing (CORS) headers.
Use this guide to choose appropriate values for your CORS headers. Adjust settings to balance security and usability based on your API’s needs.
1. Access-Control-Allow-Origin
- Specific Domain (e.g.,
https://example.com)- Restricts access to only trusted sites.
- Use with credentials or sensitive data.
- Dynamically Set Origin
- Read the request’s
Originheader and echo it back when it matches an allow-list. - Prevents wildcard issues when using cookies or HTTP auth.
- Read the request’s
- Wildcard (
*)- Allows any site when credentials are NOT involved.
- Do not use with
Access-Control-Allow-Credentials: true.
Never combine
* with credentials—browsers will ignore the wildcard and refuse the request.2. Access-Control-Allow-Credentials
true- Enable when your API must accept cookies, HTTP authentication, or client certificates.
- Must be paired with a non-wildcard
Access-Control-Allow-Origin.
- Omit or
false- Safer default if your API is completely public or stateless.
Omitting this header prevents browser-side credential leaks by default.
3. Access-Control-Allow-Methods
- List only the HTTP methods your API actually supports. For example:
Access-Control-Allow-Methods: GET, POST
- Avoid advertising methods you don’t implement (e.g.,
DELETE,PUT,PATCH) to reduce attack surface.
4. Access-Control-Allow-Headers
- Specify only the headers your clients need to send. Common examples:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
- Excluding unnecessary headers prevents unexpected or malicious data from being sent.
5. Access-Control-Max-Age
- Controls how long the browser caches preflight responses (in seconds).
- Performance vs. Security:
- Longer cache (e.g.,
86400seconds = 24 hours) reduces preflight overhead. - Shorter cache (e.g.,
600seconds) ensures policy changes take effect sooner.
- Longer cache (e.g.,
A common compromise is 3600 (1 hour) for dynamic APIs, or 86400 (24 hours) for stable endpoints.
6. Access-Control-Expose-Headers
- Use when client-side JavaScript must read custom response headers beyond the CORS-safelisted ones.
- Example:
Access-Control-Expose-Headers: X-Total-Count, X-Request-ID
- If omitted, browsers only expose simple headers (
Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma).
Example Configuration Snippet (Express.js)
app.use((req, res, next) => {
const allowedOrigins = ['https://app.example.com'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.header('Access-Control-Allow-Origin', origin);
res.header('Access-Control-Allow-Credentials', 'true');
}
res.header('Access-Control-Allow-Methods', 'GET,POST');
res.header(
'Access-Control-Allow-Headers',
'Content-Type, Authorization, X-Requested-With'
);
res.header('Access-Control-Max-Age', '3600');
res.header('Access-Control-Expose-Headers', 'X-Total-Count, X-Request-ID');
if (req.method === 'OPTIONS') {
return res.sendStatus(204);
}
next();
});
Summary
- Origin: Prefer specific domains or dynamic allow-lists over
*when using credentials. - Credentials: Only enable if necessary and always pair with a non-wildcard origin.
- Methods & Headers: Restrict to what your API supports and expects.
- Caching: Tune
Max-Agefor your performance/security needs. - Expose: Declare any custom headers you need on the client side.
Keep this cheatsheet handy to ensure your CORS configuration remains secure and efficient!