Why doesn't this localhost cookie get set in the browser? - cookies

In a server I'm building I want to set a cookie with an auth token that gets set when the user logs in. The login request is a POST XHR with a form containing my username and password. I'm testing this on http://localhost:3000.
I can see that the server is trying to set the cookie because the response has this header:
set-cookie: token=json-web-token-value;Expires=Fri, 12 Mar 2021 18:19:12 GMT
However Chrome seems to be ignoring this. No subsequent requests to the API contain the cookie and it also isn't in the list of cookies for http://localhost:3000 in the Application -> Cookies devtools section.
When I try to set the cookie with JS manually like
document.cookie = 'token=json-web-token-value;Expires=Fri, 12 Mar 2021 18:19:12 GMT'
then the cookie does get set correctly. So the problem clearly isn't with the contents of the cookie itself.
What am I doing wrong here?
EDIT: Firefox
I decided to check whether Firefox works any differently, and lo and behold the cookie does get set. The only thing that seemed odd is that the path was set to /auth – possibly because the login endpoint path is /auth/login. Setting the path in my server to / manually results in a cookie of
token=json-web-token-value;Path=/;Expires=Fri, 12 Mar 2021 18:34:27 GMT
which now seems to work even in Chrome!
So now my questions are:
Why does leaving the path undefined make Chrome completely ignore the cookie?
Why does not specifying a path make Firefox set the path to /auth and not /, or /auth/login for that matter?

Related

Mysterious Django API Behavior In Production

Long time reader but newly joined the community. I have a mysterious issue that I would like to seek help with. Since this is a part of the code that is currently running in production I need to redact parts of the info and will provide information is and when required. If needed I will also make a new sample code to make sure we can all test and also guide me the right way to troubleshoot the issue.
Currently, there is an web application ( django/wagtail/coderedcms ) backend that need to be converted into a mobile app. To allow the mobile app to communicate with the Backend server, I have implemented an API endpoint using the Django-rest-framework. To authenticate the user, I have already implemented a simple authentication endpoint using Django-rest-simplejwt. This part is working fine. One of the requirement for the app is that the user must be able to view/update their profile through the mobile app.
When working in dev server in my localhost, The behaviour is as intended, each user may login using the application, the backend will send back a token, and the tokan will be use subsequently to access the various part off the application.
When the same codebase is being implemented in production( currently in UAT stage) one behaviour that is found, If multiple user is logged in at the same time, The server will only return the profile of the first user that request the profile.
meaning :
user A logged in ....
user B logged in ....
user B request to view his profile ( profile B is shown)
user A request to view his profile ( profile B is shown) <- correct behaviour should be Profile A is shown
This baffled me as during testing on localhost, the behavior are:
user A logged in ....
user B logged in ....
user B request to view his profile ( profile B is shown)
user A request to view his profile ( profile A is shown)
I dont know if this is due to docker, nginx or the django production setting.
However, now I can only narrow down to Nginx and docker as I am using the same configuration in localhost beside the debug=true status.
Any help or pointer would be useful.
I thank you in advance for all that read and answer this silly but mysterious question
Sincerely,
Ashraf
Edit
In reply to Ogulcan Olguner
from production server Postman wield this in the header responds
allow →GET, POST, OPTIONS
cache-control →max-age=300
connection →keep-alive
content-encoding →gzip
content-type →application/json
date →Wed, 25 Nov 2020 20:59:03 GMT
expires →Wed, 25 Nov 2020 21:03:30 GMT
server →nginx/1.17.4
strict-transport-security →max-age=31536000
transfer-encoding →chunked
vary →Accept, Origin, Cookie
x-cdn →Incapsula
x-content-type-options →nosniff
x-frame-options →ALLOWALL
x-iinfo →4-22327133-22328885 NNYN CT(2 2 0) RT(1606337880159 62932) q(0 0 0 -1) r(1 1) U16
x-wagtail-cache →hit
for LocalHost
allow →POST, GET, OPTIONS
content-length →204
content-type →application/json
date →Wed, 25 Nov 2020 20:57:45 GMT
server →WSGIServer/0.2 CPython/3.8.5
vary →Accept, Origin
x-content-type-options →nosniff
x-frame-options →DENY
I am guessing since there is not much information about why the error could be caused. If you are not running a separate cache system in production (such as Redis), this error may be caused by the client. Have you tried the same scenario with a tool like Postman?

JSessionID cookie being set with J2EE session variables option unchecked

I am running Coldfusion 10 Update 14 (10,0,14,291717).
Is it normal for the jsessionid cookie to be set when the "Use J2EE session variables" option is unchecked in the cfadmin.
It is being set in the response from a page that is posted to using a form with enctype set to multipart/form-data. It seems to happen with any form in our application if I change the enctype. That is the only time I see it being set. There could be other conditions that cause it to be set, but I haven't found any. It doesn't happen if the form has no enctype set. It also doesn't happen for get requests.
Should this cookie ever be set if the option is unchecked in the cfadmin?
Is it normal for it to only be set with this particular type of post request?
This happens on my development machine Mac OSX 10.9.5 and on our production server running Windows Server and IIS.
These are the response headers from the page that sets the cookie. The page does some form processing and then does a cflocation.
HTTP/1.1 302 Found
Date: Wed, 10 Dec 2014 20:42:21 GMT
Server: Apache/2.2.26 (Unix) DAV/2 mod_jk/1.2.32 mod_ssl/2.2.26 OpenSSL/0.9.8za
Set-Cookie: JSESSIONID=A61590143D1AD60644B208F25990F8FA.cfusion; Path=/; HttpOnly
Location: http://localhost/ethm/maintenanceForm/mrformv7/main.cfm?pid=home&BID=1995
Cache-Control: no-cache
Pragma: no-cache
Keep-Alive: timeout=5, max=49
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html;charset=UTF-8
More Information:
I updated my development cf to update 15 so the version is now 10,0,15,292620.
I created a new folder in my local site and put the following 2 files in the folder:
Application.cfc
component{
}
index.cfm
<form enctype="multipart/form-data" method="post" action="index.cfm">
<input type="submit" value="Go">
</form>
Then if I clear my cookies and go to that page I get no new cookies. If I submit the form I get a JSessionID cookie. I can clear it and I get a new one every time I submit the form. If I don't clear my cookies the same one stays.
We tested this for you Mat (Wil Genovese) on CF10 UPdate 15. According to Wil CF does not set J2EE session cookeies if they are disabled in the CF Admin. However if an existing j2ee session cookie exists from when they were anabled it will persist until it expires. Hopefully that helps a little.
FYI - this was not on OSX.
EDIT: More information
Further testing revealed the following Matt.
When you issue a POST using multipart/form-data this condition (a J2EE cookie set) will always occur. If you change your POST header to /application/x-www-form-urlencoded it will not be set. And a GET request will not allow it to be set.
Using this Application.cfc (adding or subtracting settings and names):
component
{
THIS.name = "je22test";
THIS.Sessionmanagement = true;
THIS.ApplicationTimeout = CreateTimeSpan(1,0,0,0);
THIS.SessionTimeout = createtimespan(0,0,20,0);
THIS.SetClientCookies = false;
}
...does not appear to have any effect. We are going to log it as a bug. I'm not sure the impact exactly. It might red flag a security scan - but you really should use rotating J2EE sessions anyway. Still, a scan might notice that it only rotates on a POST request. It would see it, then flag it (as an info warning probably) for not rotating. Not sure that's enough of a bug to fix or worry about, but lets see what Adobe says eh?
I just searched through the Adobe ColdFusion bug base and found this bug report
https://bugbase.adobe.com/index.cfm?event=bug&id=3430245
This is related to what we are seeing (if not the exact same thing) and it was "fixed" in CF10u14 and CF11u3.
However, I can verify the results you're getting, as Mark already posted, in CF10. So after I found the bug report I went and tested this in CF11u3 and found that with J2EE Session variables turned off CF11u3 always sets the jsessionid cookie.
I created a new bug report with my findings and linked to the old bug report and this forum page. However, I made the mistake of tagging it as a 'security bug' because session cookies not being properly set is technically a security issue and now it's not visible to anyone including me. That will teach me.
Regards,
Wil Genovese
Sr. Web Application Developer/
Systems Administrator
CF Webtools

logging in to umbraco 6.1 backend doesn't work anymore, keep getting errors and redirect back to login.aspx page

after nog using the backend of our umbraco website for a few months I started developing for our website again. As the website was being used by some people, I decided to use a staging environment.
So I moved all my files and finally got the database also cloned.
But now whenever I try to login to the backend of umbraco (in the live and the staging environment) I get a javascript error in my firebug console:
{"Message":"The user has no umbraco contextid - try logging in","StackTrace":" at Umbraco.Web.Security.WebSecurity.ValidateCurrentUser(HttpContextBase httpContext, Boolean throwExceptions)\r\n at Umbraco.Web.Security.WebSecurity.AuthorizeRequest(HttpContextBase httpContext, Boolean throwExceptions)\r\n at Umbraco.Web.WebServices.UmbracoAuthorizedWebService.AuthorizeRequest(Boolean throwExceptions)\r\n at Umbraco.Web.WebServices.UmbracoAuthorizedWebService.AuthorizeRequest(String app, Boolean throwExceptions)\r\n at umbraco.presentation.webservices.TreeClientService.GetInitAppTreeData(String app, String treeType, Boolean showContextMenu, Boolean isDialog, TreeDialogModes dialogMode, String functionToCall, String nodeKey)","ExceptionType":"System.InvalidOperationException"}
As suggested in other posts, I delete my cookies and try again, but no luck.
I also get some other errors from time to time:
uiKeys is undefined
I uploaded my umbraco/config/lang folder using Binary, but I still get the error sometimes
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
I added this to my web.config
<pages enableEventValidation="false" validateRequest="false" viewStateEncryptionMode ="Never" />
and the error seems gone
I also got some error about synthax in the document type declaration at the start of the logout page which I get redirected to
I have been at this for several hours and can't seem to fix it.
Locally loggin in works.
Edit
I just did a fresh install of 6.1.6 and 6.1.5 and tried to logon but I still get the error:
http://staging.mydomaimn.com/umbraco/webservices/TreeClientService.asmx/GetInitAppTreeData 500 Internal server error:
{"Message":"The user has no umbraco contextid - try logging in","StackTrace":" at Umbraco.Web.Security.WebSecurity.ValidateCurrentUser(HttpContextBase httpContext, Boolean throwExceptions)\r\n at Umbraco.Web.Security.WebSecurity.AuthorizeRequest(HttpContextBase httpContext, Boolean throwExceptions)\r\n at Umbraco.Web.WebServices.UmbracoAuthorizedWebService.AuthorizeRequest(Boolean throwExceptions)\r\n at Umbraco.Web.WebServices.UmbracoAuthorizedWebService.AuthorizeRequest(String app, Boolean throwExceptions)\r\n at umbraco.presentation.webservices.TreeClientService.GetInitAppTreeData(String app, String treeType, Boolean showContextMenu, Boolean isDialog, TreeDialogModes dialogMode, String functionToCall, String nodeKey)","ExceptionType":"System.InvalidOperationException"}
This is on a fresh install that never had logins before
Perhaps the problem is with the database setup. My host uses MSSQL 2012 and I have two databases, the first is for the live version which is called 'myloginname' and the second is for the staging which is called 'myloginname_1'.
is the _1 a problem when placing the logon in the database (which I read Umbraco does)?
Edit 2
just looked in my database and Umbraco does create a contextId in the db table 'umbracoUserLogins' but does not create the cookie which should contain the same 'UMB_UCONTEXT'
so this is probably my real problem, what could be causing this?
Edit: some more info on this:
When I look in Fiddler I can see this:
On the 'Raw' tab:
HTTP/1.1 302 Found Cache-Control: private Content-Type: text/html;
charset=utf-8 Location: /umbraco/ Set-Cookie:
ASP.NET_SessionId=zjlqfoxq421wmnpeydcbxv1t; path=/; HttpOnly
Set-Cookie: ASP.NET_SessionId=zjlqfoxq421wmnpeydcbxv1t; path=/;
HttpOnly Set-Cookie: UMB_UCONTEXT=694C3[...a lot of text...]CFDD5EDB;
expires=Tue, 12-Nov-2013 14:07:23 GMT; path=/; HttpOnly Date: Mon, 11
Nov 2013 14:07:23 GMT Content-Length: 126
The cookie tab shows:
Response sent 1318 bytes of Cookie data: Set-Cookie:
UMB_UCONTEXT=694C3[...a lot of text...]D5EDB; expires=Tue, 12-Nov-2013
14:07:23 GMT; path=/; HttpOnly This response did not contain a P3P
Header.
So we can conclude:
the expiration time and date are correct
there is a 302 error, but this seems to be for all cookies and the
other two mentioned are created (I'm confused about this)
perhaps the P3P headers are an issue?
I was able to fix this.
The reason why the UMB_UCONTEXT cookie wasn't created was that I fixed the error
Validation of viewstate MAC failed. If this application is hosted by a
Web Farm or cluster, ensure that configuration specifies the same
validationKey and validation algorithm. AutoGenerate cannot be used in
a cluster.
the wrong way. As How To Fix the: “Validation of viewstate MAC failed” Error (ASP.NET MVC) shows, I needed to create a random machinekey and add it to my web.config

Cookies on localhost with explicit domain

I must be missing some basic thing about cookies. On localhost, when I set a cookie on server side and specify the domain explicitly as localhost (or .localhost). the cookie does not seem to be accepted by some browsers.
Firefox 3.5: I checked the HTTP request in Firebug. What I see is:
Set-Cookie:
name=value;
domain=localhost;
expires=Thu, 16-Jul-2009 21:25:05 GMT;
path=/
or (when I set the domain to .localhost):
Set-Cookie:
name=value;
domain=.localhost;
expires=Thu, 16-Jul-2009 21:25:05 GMT;
path=/
In either case, the cookie is not stored.
IE8: I did not use any extra tool, but the cookie does not seem to be stored as well, because it’s not being sent back in subsequent requests.
Opera 9.64: Both localhost and .localhost work, but when I check the list of cookies in Preferences, the domain is set to localhost.local even though it’s listed under localhost (in the list grouping).
Safari 4: Both localhost and .localhost work, but they are always listed as .localhost in Preferences. On the other hand, a cookie without an explicit domain, it being shown as just localhost (no dot).
What is the problem with localhost? Because of such a number of inconsistencies, there must be some special rules involving localhost. Also, it’s not completely clear to me why domains must be prefixed by a dot? RFC 2109 explicitly states that:
The value for the Domain attribute
contains no embedded dots or does not
start with a dot.
Why? The document indicates that it has to do something with security. I have to admit that I have not read the entire specification (may do it later), but it sounds a bit strange. Based on this, setting cookies on localhost would be impossible.
By design, domain names must have at least two dots; otherwise the browser will consider them invalid. (See reference on http://curl.haxx.se/rfc/cookie_spec.html)
When working on localhost, the cookie domain must be omitted entirely. You should not set it to "" or NULL or FALSE instead of "localhost". It is not enough.
For PHP, see comments on http://php.net/manual/en/function.setcookie.php#73107.
If working with the Java Servlet API, don't call the cookie.setDomain("...") method at all.
I broadly agree with #Ralph Buchfelder, but here's some amplification of this, by experiment when trying to replicate a system with several subdomains (such as example.com, fr.example.com, de.example.com) on my local machine (OS X / Apache / Chrome|Firefox).
I've edited /etc/hosts to point some imaginary subdomains at 127.0.0.1:
127.0.0.1 localexample.com
127.0.0.1 fr.localexample.com
127.0.0.1 de.localexample.com
If I am working on fr.localexample.com and I leave the domain parameter out, the cookie is stored correctly for fr.localexample.com, but is not visible in the other subdomains.
If I use a domain of ".localexample.com", the cookie is stored correctly for fr.localexample.com, and is visible in other subdomains.
If I use a domain of "localexample.com", or when I was trying a domain of just "localexample" or "localhost", the cookie was not getting stored.
If I use a domain of "fr.localexample.com" or ".fr.localexample.com", the cookie is stored correctly for fr.localexample.com and is (correctly) invisible in other subdomains.
So the requirement that you need at least two dots in the domain appears to be correct, even though I can't see why it should be.
If anyone wants to try this out, here's some useful code:
<html>
<head>
<title>
Testing cookies
</title>
</head>
<body>
<?php
header('HTTP/1.0 200');
$domain = 'fr.localexample.com'; // Change this to the domain you want to test.
if (!empty($_GET['v'])) {
$val = $_GET['v'];
print "Setting cookie to $val<br/>";
setcookie("mycookie", $val, time() + 48 * 3600, '/', $domain);
}
print "<pre>";
print "Cookie:<br/>";
var_dump($_COOKIE);
print "Server:<br/>";
var_dump($_SERVER);
print "</pre>";
?>
</body>
</html>
localhost: You can use: domain: ".app.localhost" and it will work. The 'domain' parameter needs 1 or more dots in the domain name for setting cookies. Then you can have sessions working across localhost subdomains such as: api.app.localhost:3000.
When a cookie is set with an explicit domain of 'localhost' as follows...
Set-Cookie: name=value;
domain=localhost; expires=Thu, 16-Jul-2009 21:25:05 GMT; path=/
...then browsers ignore it because it does not include at least two periods and is not one of seven specially handled, top level domains.
...domains must have at least two (2) or three (3) periods in them to
prevent domains of the form: ".com", ".edu", and "va.us". Any domain
that fails within one of the seven special top level domains listed
below only require two periods. Any other domain requires at least
three. The seven special top level domains are: "COM", "EDU", "NET",
"ORG", "GOV", "MIL", and "INT".
Note that the number of periods above probably assumes that a leading period is required. This period is however ignored in modern browsers and it should probably read...
at least one (1) or two (2) periods
Note that the default value for the domain attribute is the host name of the server which generated the cookie response.
So a workaround for cookies not being set for localhost is to simply not specify a domain attribute and let the browser use the default value - this does not appear to have the same constraints that an explicit value in the domain attribute does.
Cross sites cookies problem I solved like this:
Backend
Server side
serving on: http://localhost:8080
when creating a response, set Cookie
attributes:
SameSite=None; Secure; Path=/
Client side
Frontend (in my case Angular)
serving on: http://localhost:4200/
when sending request to Server (backend)
set XHR.withCredentials=true:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/', true);
xhr.withCredentials = true;
xhr.send(null);
My interpretation:
when backend and frontend domains differ the decision if the cookies will be saved in frontend domain cookie storage from received response is brought by the browser. Browser will allow sending cookies ONLY if XHR request has withCredentials=true and correct server Cookie attributes (HTTP Set-Cookie header) are recieved
when backend and frontend domains differ the decision if the cookies will be sent within request is brought by the browser. Browser will allow this ONLY if XHR request has withCredentials=true
in other words, if withCredentials=true is ommited - cookies won't be sent within request NOR will be recieved and saved from response
recieved cookies are allways stored under frontend domain name in browser cookie storage. In case when server domain differs and cookies are saved successfully, the effect is the same as if they have been sent by frontend domain in the first place.
if SameSite=None cookie attribute is omitted today's browser (Firefox/Chrome) will use default Lax mode which is too strict for cross site cookies
if Secured cookie attribute is ommited - then SameSite=None will be ignored - it requires Secured to be set
for localhost Secured cookie property browser does not require HTTPS / SSL, http will work - no need to serve frontend or backend under https://localhost ...
EDIT 2022-03-02 - For Safari (v15.1) this is not true -> in Safari http://localhost + cookie with Secure - the cookie will be ignored, not saved in browser (solution: for Safari + http://localhost remove Secure and SameSite if provided).
EDIT 2023-01-13 - #Barnaby reported that "Firefox refuses to set it: 'has been rejected because a non-HTTPS cookie can’t be set as “secure”.'" If this is the case - solution as for Safari should work (see EDIT 2022-03-02 above).
Hints for diagnostics:
in order to check if the cookies are sent - open browser developer tools and check Network tab. Find the request to backend and check Headers - search for Cookie header in Request headers, and Set-Cookie in Response headers
in order to check if the cookies are saved - open browsers developer tools, see Storage manager (Firefox), check Cookies and search for frontend domain name, check if the cookie exists and if does, check when it was created ...
don't forget to set CORS on backend first
Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
If you're setting a cookie from another domain (ie you set the cookie by making an XHR cross origin request), then you need to make sure you set the withCredentials attribute to true on the XMLHttpRequest you use to fetch the cookie as described here
I had much better luck testing locally using 127.0.0.1 as the domain. I'm not sure why, but I had mixed results with localhost and .localhost, etc.
Results I had varied by browser.
Chrome- 127.0.0.1 worked but localhost .localhost and "" did not.
Firefox- .localhost worked but localhost, 127.0.0.1, and "" did not.
Have not tested in Opera, IE, or Safari
Spent a great deal of time troubleshooting this issue myself.
Using PHP, and Nothing on this page worked for me. I eventually realized in my code that the 'secure' parameter to PHP's session_set_cookie_params() was always being set to TRUE.
Since I wasn't visiting localhost with https my browser would never accept the cookie. So, I modified that portion of my code to conditionally set the 'secure' param based on $_SERVER['HTTP_HOST'] being 'localhost' or not. Working well now.
I hope this helps someone.
you can make use of localhost.org or rather .localhost.org it will always resolve to 127.0.0.1
The only thing that worked for me was to set Path=/ on the cookie.
Moreover, the default value of a path attribute seems to be different from browsers to browsers although I tested only two of them (Firefox and Chrome).
Chrome tries to set a cookie as is; if path attribute is omitted in Set-Cookie header then it will not be stored and ignored.
However, Firefox stores a cookie even without an explicit path attribute. It just set it with the requested path; my request url was /api/v1/users and the path was set to /api/v1 automatically.
Anyway, both browsers worked when path was set to / even without an explicit domain, ie Domain=localhost or something. So there are some differences in the way how each browser handles cookies.
None of the suggested fixes worked for me - setting it to null, false, adding two dots, etc - didn't work.
In the end, I just removed the domain from the cookie if it is localhost and that now works for me in Chrome 38.
Previous code (did not work):
document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';
New code (now working):
if(document.domain === 'localhost') {
document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';path=/;' ;
} else {
document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';
}
There seems to be an issue when you use https://<local-domain> and then http://<local-domain>. The http:// site does not send cookies with requests after https:// site sets them. Force reload and clear cache doesn't help. Only manual clearing of cookies works. Also, if I clear them on the https:// page, then http:// page starts working again.
Looks to be related to "Strict secure cookies". Good explanation here. It was released in Chrome 58 on 2017-04-19.
It looks like Chrome does in fact record both secure cookies and non-secure cookies as it will show the correct cookies depending on the page's protocol when clicking the address bar icon.
But Developer tools > Application > Cookies will not show a non-secure cookie when there is a secure cookie of the same name for the same domain, nor will it send the non-secure cookie with any requests. This seems like a Chrome bug, or if this behavior is expected, there should be some way to view the secure cookies when on a http page and an indication that they are being overridden.
Workaround is to use different named cookies depending on if they are for an http site or https site, and to name them specific to your app. A __Secure- prefix indicates that the cookie should be strictly secure, and is also a good practice because secure and non-secure won't collide. There are other benefits to prefixes too.
Using different /etc/hosts domains for https vs. http access would work too, but one accidental https://localhost visit will prevent any cookies of the same names to work on http://localhost sites - so this is not a good workaround.
I have filed a Chrome bug report.
After much experimentation and reading various posts, this worked. I could set multiple cookies, read them back and set the time negative and delete them.
func addCookie(w http.ResponseWriter, name string, value string) {
expire := time.Now().AddDate(0, 0, 1)
cookie := http.Cookie{
Name: name,
Value: value,
Expires: expire,
Domain: ".localhost",
Path: "/",
}
http.SetCookie(w, &cookie)
}
Cookie needs to specify SameSite attribute, None value used to be the default, but recent browser versions made Lax the default value to have reasonably robust defense against some classes of cross-site request forgery (CSRF) attacks.
Along with SameSite=Lax you should also have Domain=localhost, so your cookie will be associated to localhost and kept. It should look something like this:
document.cookie = `${name}=${value}${expires}; Path=/; Domain=localhost; SameSite=Lax`;
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
There is an issue on Chromium open since 2011, that if you are explicitly setting the domain as 'localhost', you should set it as false or undefined.
I had the same issue and I fixed it by putting 2 dots in the cookie name itself without specifying any domain.
set-cookie: name.s1.s2=value; path=/; expires=Sun, 12 Aug 2018 14:28:43 GMT; HttpOnly
Tried all of the options above. What worked for me was:
Make sure the request to server have withCredentials set to true. XMLHttpRequest from a different domain cannot set cookie values for their own domain unless withCredentials is set to true before making the request.
Do not set Domain
Set Path=/
Resulting Set-Cookie header:
Set-Cookie: session_token=74528588-7c48-4546-a3ae-4326e22449e5; Expires=Sun, 16 Aug 2020 04:40:42 GMT; Path=/
I had a similar problem where my backend and frontend were running on localhost but different ports. To fix this I omitted the Domain in the Set-Cookie and used withCredentials: true in my request options.
see here
document.cookie = valuename + "=" + value + "; " + expires + ";domain=;path=/";
this "domain=;path=/"; will take dynamic domain as its cookie will work in subdomain.
if u want to test in localhost it will work
None of the answers here worked for me. I fixed it by putting my PHP as the very very first thing in the page.
Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
From http://php.net/manual/en/function.setcookie.php
I was playing around a bit.
Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=localhost; Path=/
works in Firefox and Chrome as of today. However, I did not find a way to make it work with curl. I tried Host-Header and --resolve, no luck, any help appreciated.
However, it works in curl, if I set it to
Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=127.0.0.1; Path=/
instead. (Which does not work with Firefox.)
Another important detail, the expires= should use the following date time format: Wdy, DD-Mon-YYYY HH:MM:SS GMT (RFC6265 - Section 4.1.1).
Set-Cookie:
name=value;
domain=localhost;
expires=Thu, 16-07-2019 21:25:05 GMT;
path=/
If anyone is still facing this, I found that switching from a post request to a get request was needed.
I was using axios, and withCredentials: true on the frontend, but this was failing. Switching the request to get and changing my backend to match worked.

Safari doesn't set Cookie but IE / FF does

I found a strange cookie problem on safari. If you surf to http://2much.ch you can enter with FF/IE and surf inside the site.
But if you use safari, you can enter only once; you can't surf inside the site. I found that Safari doesn't set the entered cookie, but FF/IE does.
What is wrong here?
It looks like you hit a Safari bug here; you are redirecting any visiting browser to /entry while setting the cookie at the same time, and Safari is ignoring the Set-Cookie header when encountering the 302 HTTP status:
$ curl -so /dev/null -D - http://4much.schnickschnack.info/
HTTP/1.1 302 Moved Temporarily
Server: nginx/0.7.61
Date: Sun, 19 Jul 2009 12:20:49 GMT
Content-Type: text/html;charset=utf-8
Connection: keep-alive
Content-Length: 14260
Content-Language: de
Expires: Sat, 1 Jan 2000 00:00:00 GMT
Location: http://4much.schnickschnack.info/entry
Set-Cookie: colorstyle="bright"; Path=/; Expires=1248092449.12
Set-Cookie: _ZopeId="73230900A39w5NG7q4g"; Path=/
Technically, this would be a bug in Apple's Foundation Classes, I've found a WebKit bug that states this is the case.
I suppose the workaround is to set the cookie not in index_html but in entry instead.
In the intervening years since I first answered this question, this issue now appears solved, at least it was for Safari 6 when someone tested all major browsers for Set-Cookie support on 302 redirects in 2012.
A month ago, I ran into this issue. At first I thought it was a corrupted cookie jar as I could clean out the cookies and go.
However, it popped up again. This time I spent an hour going through it, watching what was sent, reviewing what safari sent back, and I found the problem.
In this case, I had an array of cookie values being sent to the browser after login prior to the redirect. The values looked something like 'user id', 'user full name', 'some other id', etc.
( yes, the id's are encrypted so no worries there )
My user full name was actually in a <lastname>, <firstname> format.
When safari was posting the cookie back to the server, everything after the comma after the lastname was dropped. It was only posting back values up to that point.
When i removed the comma the rest of the values started working just fine.
So it appears that if you send a cookie value that contains a comma, then safari doesn't properly escape that in it's internal storage. Which leads me to think that if they aren't properly escaping commas, then there are probably some security issues with safari's cookie handling code.
Incidentally, this was tested on Win 7 x64 with safari 4.0.5. Also I put up a web page at: http://cookietest.livelyconsulting.com/ which shows this exact problem.(I removed that test site)
IE, FF, and chrome all correctly set the cookie. safari does not.
Looks like this is no longer an issue. See http://blog.dubbelboer.com/2012/11/25/302-cookie.html
We've run into a very similar issue where Safari (v. 7.0.6) would ignore a cookie. The cookie header looked perfectly fine, almost identical to another cookie which was remembered.
It turned out that the culprit was the previous cookie header having a malformed expires value. Safari's handling of broken cookie headers is evidently not as robust as that of the other browsers.
I ran into same issue with Chrome. Chrome doesn't ignore the set-cookie header while you are redirecting, but you never know the order (set cookie first or redirect first). Here is something I have tried:
I have a website, which supports English and French. I implemented it (with php) this way:
localhost has a link to localhost/fr (which set-cookie to French and redirect to localhost). It works. (set cookie first)
localhost/path1 has a link to localhost/fr?return=/path1 (which set-cookie to French and redirect to localhost/path1). It doesn't work. (redirect first, the language didn't change)
localhost/path1 has a link to localhost/fr?return=www.google.com (which set-cookie to French and redirect to google). When I came back to my website again, it's in French. (which means set-cookie to French is not ignored, only executed after redirect)
Hope I make myself clear, English is a foreign language to me.
After a great deal of pain, I found out that Safari (15.3) actually does save and my cookie, but it never displayed in developer tools storage -> cookies, but it works fine.
Here's the cookie I create and return in a Netlify function.
const secureCookie = cookie.serialize('jwtToken', JSON.stringify(jwtToken), {
secure: process.env.CONTEXT !== 'dev',
domain: process.env.CONTEXT === 'dev' ? 'localhost' : '.domain.com',
httpOnly: true,
sameSite: true,
expires: new Date(Date.now() + (1000 * jwtToken.expires_in))
})
and netlify function return
return {
statusCode: 200,
headers: {
"Cache-Control": "no-cache",
},
multiValueHeaders: {
"Set-Cookie": [secureCookie],
},
body: JSON.stringify(body),
}