Glossary

Credentialed request

A credentialed request is a cross-origin fetch/XHR that carries credentials the browser manages for you: cookies, browser-managed HTTP authentication, or TLS client certificates. Browsers apply stricter CORS rules to these: no wildcards allowed, and the server has to explicitly opt in.

An Authorization header you set yourself in JavaScript does not make a request credentialed. It triggers a preflight and must be listed in Access-Control-Allow-Headers, but it works with Access-Control-Allow-Origin: *. Only credentials: 'include' (or withCredentials) rules out the wildcard.

How to make a request credentialed

// fetch: opt in via the credentials option
fetch('https://api.example.com/me', {
  credentials: 'include'   // send cookies for api.example.com
});

// XMLHttpRequest: set withCredentials
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/me');
xhr.withCredentials = true;
xhr.send();

By default fetch uses credentials: 'same-origin', which sends cookies on same-origin requests but not cross-origin. You have to ask for 'include' for credentialed cross-origin calls.

The stricter server-side rules

On a credentialed cross-origin response, the server must:

// Bad: browser will block the response
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

// Good
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Vary: Origin

Why the wildcard is forbidden

If * were allowed with credentials, any malicious site could read your authenticated responses from any other site that opted into CORS with a wildcard. The combination would defeat the whole point of same-origin policy for credentialed requests. The browser rejects the configuration as a safety net.

Common gotchas

See also

CORS Access-Control-Allow-Origin Same-origin policy Preflight