Access-Control-Allow-Headers — Permitting Custom Headers in Cross-Origin Requests
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-Headers response header lists the custom headers the browser is permitted to include in cross-origin requests, validated against the preflight Access-Control-Request-Headers value.
What You'll Learn
- How custom headers trigger preflight and header validation
- Wildcard and credentials interaction
- Best practices for header whitelisting
Why It Matters
Custom headers like Authorization, X-API-Key, or X-Request-ID are essential for modern APIs. Misconfigured Allow-Headers blocks legitimate authenticated requests. Doda Browser's extension API uses custom headers for extension authentication and version negotiation.
sequenceDiagram
Browser->>Server: OPTIONS /api/data
Browser->>Server: Access-Control-Request-Headers: Authorization, X-Custom
Server-->>Browser: Access-Control-Allow-Headers: Authorization, X-Custom
Server-->>Browser: Access-Control-Allow-Origin: https://app.example.com
Browser->>Server: GET /api/data
Browser->>Server: Authorization: Bearer token123
Browser->>Server: X-Custom: value
Server-->>Browser: 200 OK
Code Examples
// Custom headers trigger preflight automatically
fetch('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer token123',
'X-API-Version': '2'
}
});
// Browser sends Access-Control-Request-Headers:
// authorization, x-api-version
# Flask middleware for header validation
ALLOWED_HEADERS = {
'Authorization', 'Content-Type', 'X-Request-ID',
'X-API-Version', 'X-Idempotency-Key'
}
@app.after_request
def set_cors_headers(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Headers'] = \
', '.join(sorted(ALLOWED_HEADERS))
response.headers['Access-Control-Allow-Methods'] = \
'GET, POST, PUT, DELETE, OPTIONS'
response.headers['Vary'] = 'Origin'
return response
# Simulate preflight with custom headers
curl -X OPTIONS https://api.example.com/data \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: authorization, x-api-version" \
-I 2>&1 | grep -i "allow-headers"
Common Mistakes
1. Not Including Content-Type in Allow-Headers When Needed
If the browser sends Content-Type: application/json, it must be in Allow-Headers.
2. Using Case-Sensitive Header Names
Header names should be lowercase in Allow-Headers. The browser normalizes them.
3. Forgetting Authorization Header
Many APIs require Authorization but forget to include it in Allow-Headers.
4. Listing Too Many Headers
Each listed header increases preflight payload size and complexity. List only what you need.
5. Mixing Up Request and Response Headers
Allow-Headers is for request headers. Expose-Headers is for response headers JavaScript can read.
Practice Questions
- What request header does the browser send listing the custom headers it wants to include?
- Can Access-Control-Allow-Headers use a wildcard?
- Why must Content-Type be in Allow-Headers when sending JSON?
- Are header names case-sensitive in Allow-Headers?
- What happens if a requested header is not in Allow-Headers?
Answers:
- Access-Control-Request-Headers.
- Yes, modern browsers support the wildcard * for headers, but not with credentials.
- Because application/json is not a simple content type, the browser preflights and checks headers.
- No. Header names are case-insensitive and the browser normalizes them to lowercase.
- The browser blocks the actual request from being sent.
Challenge: Create an Express middleware that auto-detects which headers are used in requests and generates the minimal Allow-Headers list. Add a security warning when too many headers are allowed.
FAQ
Mini Project
Build a header validation dashboard: an Express server that logs all Access-Control-Request-Headers from preflights, compares them against the configured Allow-Headers, and reports any mismatches. Include a configuration page to update the allowed headers list at runtime.
What's Next
Learn about Access-Control-Expose-Headers to control response header visibility, then study Access-Control-Allow-Credentials for credentialed requests.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro