
Wildcard Not Allowed for Access-Control-Allow-Headers
What Does This Error Mean?
The Access-Control-Allow-Headers
response header in CORS (Cross-Origin Resource Sharing) specifies which HTTP headers are allowed in cross-origin requests.
Unlike Access-Control-Allow-Origin
, you cannot use a wildcard (*
) in Access-Control-Allow-Headers
if the request includes credentials (withCredentials: true
in JavaScript).
This error occurs when:
- The server sets
Access-Control-Allow-Headers: *
, but the request includes credentials (cookies, Authorization tokens, etc.). - A proxy (e.g., Nginx, API Gateway) misconfigures CORS headers.
- The preflight request (
OPTIONS
method) does not properly return allowed headers.
How to Fix It
1. Explicitly Define Allowed Headers
๐ Issue:
Browsers block Access-Control-Allow-Headers: *
when credentials (withCredentials: true
) are used.
โ
Fix:
List all required headers explicitly instead of using *
.
For Express.js (Node.js):
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://yourdomain.com");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
next();
});
For Flask (Python):
@app.after_request
def add_cors_headers(response):
response.headers['Access-Control-Allow-Origin'] = 'https://yourdomain.com'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
return response
2. Ensure Preflight (OPTIONS
) Requests Are Handled
๐ Issue:
When a client sends a request with custom headers (Authorization
, Content-Type
), the browser first sends an OPTIONS
preflight request. If the server does not correctly respond, the request fails.
โ
Fix:
Handle OPTIONS
requests properly.
For Express.js:
app.options("*", (req, res) => {
res.header("Access-Control-Allow-Origin", "https://yourdomain.com");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
res.send();
});
For Flask:
@app.route('/your-endpoint', methods=['OPTIONS'])
def handle_options():
response = jsonify()
response.headers['Access-Control-Allow-Origin'] = 'https://yourdomain.com'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
return response
3. Fix Client-Side Requests
๐ Issue:
The client must match the allowed headers set on the server.
โ
Fix:
Ensure the frontend does not request a wildcard (*
) and sends only the necessary headers.
Fetch API:
fetch("https://yourdomain.com/api", {
method: "POST",
credentials: "include", // Enables cookies or authentication headers
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN",
},
body: JSON.stringify({ key: "value" }),
});
Axios:
axios.post("https://yourdomain.com/api",
{ key: "value" },
{ headers: { "Content-Type": "application/json", "Authorization": "Bearer YOUR_TOKEN" }, withCredentials: true }
);
4. Allow Dynamic Headers Without Wildcard
๐ Issue:
If your API needs to support multiple frontends, manually listing all headers may be difficult.
โ
Fix:
Use Vary: Access-Control-Request-Headers
to allow dynamic headers.
For Express.js:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", req.headers.origin || "https://yourdomain.com");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", req.headers["access-control-request-headers"] || "Content-Type, Authorization");
res.header("Vary", "Access-Control-Request-Headers");
next();
});
For Flask:
@app.after_request
def add_cors_headers(response):
request_headers = request.headers.get("Access-Control-Request-Headers")
if request_headers:
response.headers["Access-Control-Allow-Headers"] = request_headers
response.headers["Vary"] = "Access-Control-Request-Headers"
return response
Conclusion
The โWildcard Not Allowed for Access-Control-Allow-Headersโ error happens because:
- Wildcards (
*
) are not allowed when credentials (withCredentials: true
) are used. - The server must explicitly list allowed headers in
Access-Control-Allow-Headers
. - The preflight request (
OPTIONS
) must be correctly handled.