Access-Control-Allow-Origin Deep Dive — Wildcard, Dynamic, and Multiple Origins
In this tutorial, you will learn about Access. We cover key concepts, practical examples, and best practices to help you master this topic.
The Access-Control-Allow-Origin header controls which origins can read the response. It accepts a single origin, the wildcard *, or null, with specific behavioral rules for each value.
What You'll Learn
- When to use wildcard vs specific origins
- How to implement dynamic origin resolution
- How to handle multiple origins and the Vary header
Why It Matters
Access-Control-Allow-Origin is the most important CORS header. Getting it wrong blocks legitimate users or opens security holes. Doda Browser's extension API uses dynamic origin validation to allow only registered extension domains.
flowchart TD
A["Request Origin: https://app.example.com"] --> B{"Server checks whitelist"}
B -->|"Origin is whitelisted"| C["Set ACAO to the request origin"]
B -->|"Origin not whitelisted"| D["Return response without ACAO"]
B -->|"Wildcard mode"| E["Set ACAO to *"]
C --> F["Include Vary: Origin"]
E --> G["Cannot use with credentials"]
style C fill:#86efac,stroke:#16a34a
style D fill:#fecaca,stroke:#dc2626
style E fill:#fef08a,stroke:#ca8a04
Code Examples
// Browser sends the Origin header automatically
// JavaScript cannot read Access-Control-Allow-Origin
// But you can infer origin access:
fetch('https://api.example.com/user', {
credentials: 'include'
}).then(response => {
// If we got here, the origin was allowed
console.log('Origin is whitelisted');
});
# Dynamic origin resolution in Flask
ALLOWED_ORIGINS = {
'https://app.example.com',
'https://dashboard.example.com',
'https://admin.example.com'
}
@app.after_request
def set_cors_origin(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Vary'] = 'Origin'
return response
// Node.js dynamic origin with cors package
const cors = require('cors');
const corsOptions = {
origin: function (origin, callback) {
const whitelist = [
'https://app.example.com',
'https://dashboard.example.com'
];
// Allow requests with no origin (server-to-server, curl)
if (!origin || whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true
};
# Test Access-Control-Allow-Origin behavior
curl -I -H "Origin: https://app.example.com" \
https://api.example.com/data | grep "access-control-allow-origin"
# Test with a blocked origin
curl -I -H "Origin: https://evil.com" \
https://api.example.com/data | grep "access-control-allow-origin"
Common Mistakes
1. Using Wildcard * with Credentials
The browser rejects the response when Allow-Origin is * and Allow-Credentials is true.
2. Returning Multiple Origins in the Header
Only one origin or * is valid. Returning two origins causes the browser to reject the response.
3. Not Returning the Vary Header
Without Vary: Origin, CDNs may cache and serve the wrong origin response to different users.
4. Allowing null Origin Too Broadly
The null origin can be set by sandboxed iframes or data: URLs, making it risky to whitelist.
5. Hardcoding Origins in Frontend Code
Origins should be configured server-side, not hardcoded in client JavaScript.
Practice Questions
- What values can Access-Control-Allow-Origin take?
- Why can't you use * with credentials?
- What is the Vary: Origin header for?
- How do you support multiple origins?
- What is the null origin and why is it dangerous to allow?
Answers:
- A single origin, the wildcard *, or null.
- The wildcard indicates any origin is allowed, which contradicts the specificity required for credentialed requests.
- It tells caches to vary the cached response based on the Origin request header.
- Dynamically set the Access-Control-Allow-Origin header to the requesting origin after validation.
- The null origin is sent by sandboxed contexts. Allowing it enables attacks from sandboxed iframes.
Challenge: Implement a dynamic CORS middleware that supports a whitelist of origins, handles credentials, sets the Vary header, and logs rejected origins for security monitoring.
FAQ
Mini Project
Build an origin whitelist service: a middleware that reads from a database or config file, validates incoming origins, sets the appropriate Access-Control-Allow-Origin, and logs rejected origins. Include a test suite that verifies correct behavior for allowed, denied, and missing origins.
What's Next
Explore Access-Control-Allow-Methods to control which HTTP methods are permitted, then study Access-Control-Allow-Headers for custom header handling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro