Why Chrome can’t set cookie
If you want to do some background reading then I suggest you look for guides to CORS (cross-origin resource sharing) and, specifically, how to set cookies when using CORS.
Using your original code you'll need to change it to set withCredentials
to true
:
let response = await axios({
method: 'post',
url: 'http://127.0.0.1:3000/api/login', // my Node server on 3000 port
data: {
email : login,
password: password,
},
withCredentials: true
})
Behind the scenes this will set the withCredentials
flag on XMLHttpRequest
:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
You'll then get CORS errors in your console. If you work your way through those errors you should be able to get it working. These errors will include...
Firstly, the server will need to return the header Access-Control-Allow-Credentials: true
. This also applies to the preflight OPTIONS request.
Secondly, you're currently using Access-Control-Allow-Origin: *
but that isn't allowed for requests using credentials. That'll need to be Access-Control-Allow-Origin: http://www.example.com
. Likewise for the preflight.
At that point the cookie should be set in most browsers (more on browser quirks later).
To get the cookies added to subsequent requests you'll also need to set withCredentials: true
on those requests. The other header changes outlined above also need to be applied. The cookies will not be included on the preflight request, just the main request.
Seeing the cookies in the browser's developer tools is not completely straightforward. Generally the tools only show cookies set for the same origin as the current page, which doesn't include the cookies set via CORS requests. To see those cookies you'll need to open another browser tab and set the URL to something that starts with the same origin as the CORS request. Be careful though, you need to pick a URL that won't set the cookies itself, otherwise that doesn't really prove anything.
Another way to check what cookies are set is to send another request (with withCredentials
) and see what cookies get sent.
Then we have the browser-specific issues...
In Safari it is really difficult to get cookies to set over CORS. If Safari is a target browser for you then I suggest doing some further research into that.
Secondly, Chrome 80 is due to change the rules around CORS cookies significantly. See:
https://www.chromium.org/updates/same-site
You'll already see warnings about this in your console with older versions of Chrome. In short, CORS cookies will need to be served over https
and set the directives Secure
and SameSite=None
.
Update:
Since writing this answer I have created an FAQ for common CORS problems. The section explaining the use of cookies can be found at https://cors-errors.info/faq#cdc8.
Set-Cookie is not working in Chrome and Dolphin - with two websites
A cookie ... was set without the `SameSite` attribute.
Starting July 14 (2020), you should set these 1,2 and upgrade to Django 3.1 3,4 (released Aug 4):
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'None'
Explanation
Before Django 3.1, the samesite
attribute is not set if the setting is the None
singleton:
if samesite:
if samesite.lower() not in ('lax', 'strict'):
raise ValueError('samesite must be "lax" or "strict".')
self.cookies[key]['samesite'] = samesite
As of Django 3.1, the samesite
attribute is set for the 'None'
string; still not for None
/False
:
if samesite:
if samesite.lower() not in ('lax', 'none', 'strict'):
raise ValueError('samesite must be "lax", "none", or "strict".')
self.cookies[key]['samesite'] = samesite
References
- Cookies default to SameSite=Lax - Chrome Platform Status
- Reject insecure SameSite=None cookies - Chrome Platform Status
- Settings | Django documentation | Django #std:setting-SESSION_COOKIE_SAMESITE
- Allowed setting SameSite cookies flags to 'None' · Pull Request #11894 · django/django
setcookie() do not set value in chrome
If your using CakePHP why not do it their way?
public $components = array('Cookie');
$cookieTime = '8 weeks'; //The amount of time you want the cookie to last
if ( !empty($voice_choice) )
this->Cookie->write('voice_choice', $voice_choice, true, $cookieTime);
Also for debugging cookies a nice trick in Chrome is:
Inspect Element -> Resources Tab -> Cookies -> yoursite (local.yoursite.com) to see if the cookie is being written.
Can't set cookie in Chrome Dev tools on localhost
Turned out I have to set an expiration date for MyCookie (all this in DevTools). However, this is confusing because:
- I'm pretty much sure it worked without an expiation date before.
- i18next cookie has no expiration date and sits there just fine.
Related Topics
Set Session Variable Using JavaScript in PHP
Pre-Incrementation VS. Post-Incrementation
PHP Simplexml Namespace Problem
How to Throttle My Site's API Users
Get Next and Previous Day with PHP
Calculating Distance Between Zip Codes in PHP
What Is the Best Practice to Export Canvas with High Quality Images
How to Pull First 100 Characters of a String in PHP
Failed to Open Stream: Http Wrapper Does Not Support Writeable Connections
PHP Preg_Match to Find Whole Words
"Strict Standards: Only Variables Should Be Passed by Reference" Error
Trim Unicode Whitespace in PHP 5.2
Remove Accents Without Using Iconv
How to Split a String in PHP at the Nth Occurrence of a Needle
Getting All Dates for Mondays and Tuesdays for the Next Year
Get Value from JSON Array in PHP