@atomkirk's answer didn't apply to me because
- I don't use the
fetch API
- I was making cross-site requests (i.e. CORS)
NOTE: If your server is using Access-Control-Allow-Origins:* (aka "all origins"/"wildcard origins"), you may not be able to send credentials (see below).
As for the fetch API; CORS requests will need {credentials:'include'} for both sending & receiving cookies
For CORS requests, use the "include" value to allow sending
credentials to other domains:
fetch('https://example.com:1234/users', {
credentials: 'include'
})
... To opt into accepting cookies from the server, you must use the credentials option.
{credentials:'include'} just sets xhr.withCredentials=true
Check fetch code
if (request.credentials === 'include') {
xhr.withCredentials = true
}
So plain Javascript/XHR.withCredentials is the important part.
If you're using jQuery, you can set withCredentials (remember to use crossDomain: true) using $.ajaxSetup(...)
$.ajaxSetup({
crossDomain: true,
xhrFields: {
withCredentials: true
}
});
If you're using AngularJS, the $http service config arg accepts a withCredentials property:
$http({
withCredentials: true
});
If you're using Angular (Angular IO), the common.http.HttpRequest service options arg accepts a withCredentials property:
this.http.post<Hero>(this.heroesUrl, hero, {
withCredentials: true
});
As for the request, when xhr.withCredentials=true; the Cookie header is sent
Before I changed xhr.withCredentials=true
- I could see Set-Cookie name & value in the response, but Chrome's "Application" tab in the Developer Tools showed me the name and an empty value
- Subsequent requests did not send a
Cookie request header.
After the change xhr.withCredentials=true
- I could see the cookie's name and the cookie's value in the Chrome's "Application" tab (a value consistent with the Set-Cookie header).
- Subsequent requests did send a
Cookie request header with the same value, so my server treated me as "authenticated"
As for the response: the server may need certain Access-Control... headers
For example, I configured my server to return these headers:
- Access-Control-Allow-Credentials:true
- Access-Control-Allow-Origin:https://{your-origin}:{your-port}
EDIT: this approach won't work if you allow all origins/wildcard origins, as described here (thanks to @ChandanBhattad) :
The CORS request was attempted with the credentials flag set, but the server is configured using the wildcard ("*") as the value of Access-Control-Allow-Origin, which doesn't allow the use of credentials.
Until I made this server-side change to the response headers, Chrome logged errors in the console like
Failed to load https://{saml-domain}/saml-authn: Redirect from https://{saml-domain}/saml-redirect has been blocked by CORS policy:
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin https://{your-domain} is therefore not allowed access.
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
After making this Access-* header change, Chrome did not log errors; the browser let me check the authenticated responses for all subsequent requests.