CORS Wildcard and Credentials Conflict — Why You Cannot Combine Asterisk with Auth
In this tutorial, you will learn about CORS Wildcard and Credentials Conflict. We cover key concepts, practical examples, and best practices to help you master this topic.
The CORS specification explicitly forbids using the wildcard * for Access-Control-Allow-Origin when Access-Control-Allow-Credentials is true, creating a conflict that blocks credentialed requests to wildcard-allowed endpoints.
What You'll Learn
- Why the wildcard and credentials cannot coexist
- The security rationale behind this restriction
- How to properly configure credentialed CORS
Why It Matters
This is the most common CORS Misconfiguration. Developers set Allow-Origin to * for simplicity, then enabling credentials causes mysterious failures. DodaTech's security team reviews all API CORS configurations specifically for this conflict.
flowchart TD
A["Server configures CORS"] --> B{"Allow-Origin = *?"}
B -->|"Yes"| C{"Allow-Credentials = true?"}
C -->|"Yes"| D["BROWSER BLOCKS RESPONSE"]
C -->|"No"| E["Works for public data"]
B -->|"No, specific origin"| F{"Allow-Credentials = true?"}
F -->|"Yes"| G["Works for authenticated data"]
F -->|"No"| H["Works for public data"]
style D fill:#fecaca,stroke:#dc2626
style G fill:#86efac,stroke:#16a34a
Code Examples
// This will fail - wildcard + credentials
fetch('https://api.example.com/user/profile', {
credentials: 'include'
});
// Browser error: "Access-Control-Allow-Origin cannot be *
// when credentials are true"
// This works - specific origin + credentials
fetch('https://api.example.com/user/profile', {
credentials: 'include'
});
// Server must respond with:
// Access-Control-Allow-Origin: https://app.example.com
// Access-Control-Allow-Credentials: true
# BROKEN: wildcard with credentials
@app.after_request
def broken_cors(response):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response # Browser will block this
# FIXED: specific origin with credentials
@app.after_request
def fixed_cors(response):
origin = request.headers.get('Origin', '')
if origin in ['https://app.example.com', 'https://admin.example.com']:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Vary'] = 'Origin'
return response
// Express: this will cause the conflict
app.use(cors({
origin: '*',
credentials: true // This will fail
}));
// Express: correct way
app.use(cors({
origin: ['https://app.example.com'],
credentials: true
}));
# Test the conflict
curl -I -H "Origin: https://app.example.com" \
https://api.example.com/data | grep -i "access-control"
# If ACAO: * and ACAC: true appear together
# the browser will reject the response
Common Mistakes
1. Setting Origin to * Then Wondering Why Credentials Fail
This is the root cause of most credentialed CORS issues.
2. Trying to Use Multiple Origins in a Single Header
ACAO does not support multiple values. Use dynamic resolution.
3. Setting Credentials to True Without Changing Origin from *
Both changes must be made together: specific origin + credentials true.
4. Assuming the Error Message Explains the Conflict
The browser shows a generic CORS error. Developers must know to check for this specific conflict.
5. Testing with Curl and Not Seeing the Issue
Curl does not enforce CORS. The conflict only appears in browsers.
Practice Questions
- Why does the CORS spec forbid wildcard with credentials?
- What browser error appears when this conflict occurs?
- How do you fix the wildcard + credentials conflict?
- Does this conflict apply to Allow-Methods and Allow-Headers wildcards?
- Can you use Allow-Origin: * with Access-Control-Expose-Headers: * and credentials?
Answers:
- For security. If any origin can make credentialed requests, user data is exposed to all websites.
- A generic CORS error: "Access to fetch at X has been blocked by CORS policy."
- Change Allow-Origin from * to the specific requesting origin.
- Yes. When credentials are true, Access-Control-Allow-Methods and Access-Control-Allow-Headers also cannot use wildcards.
- No. The same restriction applies to Expose-Headers when credentials are true.
Challenge: Write a browser script that detects the wildcard + credentials conflict by inspecting response headers. Create a report showing which endpoints have this misconfiguration.
FAQ
Mini Project
Create a CORS configuration validator: a CLI tool that reads your server configuration, detects the wildcard + credentials conflict, and suggests the correct configuration. Include test cases for Express, Flask, Django, and NGINX configurations. Generate a report of all potential CORS misconfigurations.
What's Next
Learn how to handle multiple origins in CORS without using wildcards, then explore dynamic origin whitelisting for production APIs.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro