Access-Control-Allow-Credentials — Handling Cookies and Auth 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-Credentials header tells the browser that the server permits credentials such as cookies, authorization headers, or TLS client certificates to be included in cross-origin requests.
What You'll Learn
- When and why to use credentials with CORS
- Restrictions when using credentials with CORS
- How to configure credentials on client and server
Why It Matters
Many APIs require session cookies or authentication tokens. Without credentials support, users must re-authenticate for every cross-origin request. Doda Browser's authenticated API uses credentialed CORS to maintain session state across its web interface and browser extension.
flowchart TD
A["Client sets credentials: 'include'"] --> B["Browser adds credentials to request"]
B --> C{"Server response has ACAO = specific origin?"}
C -->|"Yes"| D{"ACAO is not *?"}
D -->|"Yes"| E{"ACAC is true?"}
E -->|"Yes"| F["Response exposed to JS"]
C -->|"No"| G["Blocked: no ACAO"]
D -->|"No, ACAO = *"| H["Blocked: wildcard with credentials"]
E -->|"No"| I["Blocked: credentials not allowed"]
style F fill:#86efac,stroke:#16a34a
style G fill:#fecaca,stroke:#dc2626
style H fill:#fecaca,stroke:#dc2626
style I fill:#fecaca,stroke:#dc2626
Code Examples
// Client-side: include credentials with fetch
fetch('https://api.example.com/user/profile', {
method: 'GET',
credentials: 'include' // Send cookies cross-origin
}).then(response => {
return response.json();
});
// With XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/user/profile', true);
xhr.withCredentials = true;
xhr.send();
# Flask server allowing credentialed requests
@app.after_request
def handle_credentials(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
# Must be specific origin, not *
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Vary'] = 'Origin'
return response
// Express with credentials support
const cors = require('cors');
const corsOptions = {
origin: ['https://app.example.com', 'https://admin.example.com'],
credentials: true, // Allow cookies/auth headers
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
};
app.use(cors(corsOptions));
# Test credentialed CORS
curl -I -H "Origin: https://app.example.com" \
-H "Cookie: session=abc123" \
https://api.example.com/profile | grep -i "access-control"
Common Mistakes
1. Setting Allow-Origin to * with Credentials
The browser blocks the response if Allow-Origin is * and Allow-Credentials is true.
2. Forgetting to Set withCredentials on the Client
If the client does not set credentials: include, no cookies are sent even if the server allows them.
3. Omitting the Vary: Origin Header
Without Vary: Origin, cached responses with credentials may be served to the wrong origin.
4. Using Credentials with CDN-Cached Endpoints
CDN Caching breaks credentialed requests. Use Cache-Control: private for credentialed responses.
5. Allowing Credentials on Wildcard Subdomain Origins
A dynamic origin that matches *.example.com must be exact, not a pattern. Validate the specific origin.
Practice Questions
- What does Access-Control-Allow-Credentials: true enable?
- Why can't you use * for Allow-Origin with credentials?
- What client-side fetch option sends cookies cross-origin?
- What Vary header should you set with credentialed CORS?
- Can credentialed CORS work with public CDN caching?
Answers:
- It allows the browser to include cookies, auth headers, and client certificates.
- The wildcard means any origin is allowed, which is incompatible with the security model of credentialed requests.
- credentials: 'include'.
- Vary: Origin.
- No. Credentialed responses must use Cache-Control: private or no-cache.
Challenge: Set up a full-stack application with a frontend on localhost:3000 and an API on localhost:3001. Implement login on the API, send session cookies via credentialed CORS, and verify the session persists across requests.
FAQ
Mini Project
Build a cross-origin authentication system: a login page on one origin that authenticates against an API on another origin. Use credentialed CORS to send and receive session cookies. Implement CSRF protection using the SameSite attribute and the state parameter. Test the complete login flow with browser developer tools.
What's Next
Optimize preflight performance with Access-Control-Max-Age, then explore the wildcard and credentials conflict in detail.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro