I have an Express 4.x app, and I pass a cookie to the browser with
res.cookie('foo','bar1', {maxAge:99999999999});
it expires in the distant future. However, 5 minutes later, I get another request from the same user, and I want to give them a new cookie.
res.cookie('foo','bar2', {maxAge:99999999999});
From my debugging, it looks like the new cookie doesn't overwrite the old cookie? Is that the case? How can I update/overwrite the old cookie with the new one?
I am about 99% certain that using the {overwrite: true} property will do the trick - from here:
https://www.npmjs.com/package/cookies
it says:
cookies.set( name, [ value ], [ options ] ) This sets the given cookie
in the response and returns the current context to allow chaining.
If the value is omitted, an outbound header with an expired date is
used to delete the cookie.
If the options object is provided, it will be used to generate the
outbound cookie header as follows:
maxAge: a number representing the milliseconds from Date.now() for
expiry expires: a Date object indicating the cookie's expiration date
(expires at the end of session by default). ... overwrite: a boolean
indicating whether to overwrite previously set cookies of the same
name (false by default). If this is true, all cookies set during the
same request with the same name (regardless of path or domain) are
filtered out of the Set-Cookie header when setting this cookie.
So that would be, in Node.js Express parlance:
res.cookie('cdt_app_token', encoded, {maxAge: 90000000, httpOnly: true, secure: false, overwrite: true});
Note that if you are using a non SSL or non TLS connection, cookies may not work if secure is true.
Related
Context:
In our Node.js & express based app I updated the cookie settings from
res.cookie(newCookieName, sessionCookie, {
domain: getCookiesDomain(),
maxAge: ms('30 days'),
secure: true,
httpOnly: true
});
To this slightly different options by adding explicitly sameSite property:
res.cookie(newCookieName, sessionCookie, {
domain: getCookiesDomain(),
maxAge: ms('30 days'),
secure: true,
httpOnly: true,
sameSite: 'lax'
});
And as result, I see 2 values of cookies stored at browser, probably due different sameSite values ("default" and explicitly set lax value).
Browser: Chrome 102, OS: Windows 11.
Who else experienced this double-cookies at case of updated cookie settings?
Update
Possible cause is that at least Chrome (or may be other browsers as well?) threat different configuration of these flags and options like HttpOnly, Secure or SameSite as part of cookie full identity, among with origin and name of cookie.
It is possible to mitigate this problem by these tactics:
if you use some different format in new version of cookie, like s:value.signature in old cookie and prefix.JWT_base64url you will have to scan all arriving cookie values by parsing manually arriving Cookie header to be able detect this case. Standard Express cookie parsing code for express-session useless in this tricky scenario.
The second part is to clear manually cookies with deprecated/legacy options like Secure, HttpOnly and absent or different SameSite values. So if you did not specify SameSite, than later used Lax value and finally settled on Strict value, you will have 3 separate cookies, so you will need 2 cookie cleanup commands (2 additional set-cookie headers) set with response to clear these old versions of cookies.
Of course you can add custom properties to Request in express to mark request with flags mentioning whether such extra headers should be sent with response for request where multi-cookie issue was detected to send extra cleanup set-cookie headers with empty value and negative maxAge in res.cookie cleanup call only when such custom flags present on request, if you use this tweak.
Note that standard res.clearCookie provided by Express unaware of this issue and you can not provide the related options there, as I know.
I want to expire session when the browser is closed.
I'm using res.cookie('testlocale', 'en', { maxAge: 900000, httpOnly: true });
Also which event should i use in front end(onbeforeunload or onunlod)
I'm not able to understand how to do this. I'm using handlebars in front-end
If you use express-session.
You can set expires: false.
req.session.cookie
Each session has a unique cookie object accompany it. This allows you to alter the session cookie per visitor. For example we can set req.session.cookie.expires to false to enable the cookie to remain for only the duration of the user-agent.
From docs
If you want to manually delete cookies on frontend, I think both are good fit. But I'm not sure it's good idea.
How can I set a cookie that is not removed when the browser is closed?
The docs of res.cookie show option parameters you can pass to the method but I haven't been able to find a configuration that makes the cookie persist after closing the browser.
res.cookie('name', 'spence', { expires: 0 });
Simply set the expires parameter to some value in the future and the cookie will persist. I was getting hung up in the docs because what I thought I wanted was a "session cookie" but like its name implies, a session cookie only lasts for the duration of the browser session.
While it isn't possible to have a cookie to persist indefinitely, you can essentially do the same thing by setting the cookie to expire on some date far in the future.
var farFuture = new Date(new Date().getTime() + (1000*60*60*24*365*10)); // ~10y
res.cookie('name', 'spence', { expires: farFuture });
app.use(session({
secret: "testing credentials",
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie : {
httpOnly: true,
//secure: true,
maxAge : 60 * 60 * 1000
}
}));
I'm working on some security problems on my newly developed website. And after done some research online, if secure=true is set, then it will be more secure. However,
If set secure: true, then information inside session will lose every time when the user send another request. Is there a way to solve this problem? If doesn't include "secure: true" in the cookie: , then the session will last for that maxAge.
If a cookie is set with the secure flag, it will only be sent to the server by the browser over https, and not plain http. This should be the default for production environments.
However, when developing an app, you probably use plain http on your dev machine. If you set your session cookie as secure in this case (using plain http), the server will never receive it, and you will experience a new empty session on each request.
So in short, you should only set the cookie as secure if you are using https (that is, in later stages of your development pipeline, and definitely in production).
On another note, if you set maxAge, the cookie will be persisted, which is not the best practice for session cookies. Without maxAge, the cookie will be kept until the user closes the browser and not normally persisted to disk, which is the correct behaviour for session cookies.
It's more for my understanding. Why is there a cookie object in the req.session in express?
I use req.session to store the login status and username.
The cookie object in req.session is the same as the cookie properties in the client cookie, placed by express.parseCookie but without sessionID.
Can anyone explain why this is in there?
It cant be for the purpose to identify cookie and session because thats already made by the cookie value and the session ID (req.session.ID), or am I'm wrong?
- req.session -->
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
loggedIn: true,
username: 'luidpold' }
For convenience. It’s the cookie associated with the session, and you can query/modify it.
The session handler in Express comes from Connect. The documentation for Connect says:
Session#cookie
Each session has a unique cookie object accompany it. This allows you
to alter the session cookie per visitor. For example we can set
req.session.cookie.expires to false to enable the cookie to remain for
only the duration of the user-agent.
Session#maxAge
Alternatively req.session.cookie.maxAge will return the time remaining
in milliseconds, which we may also re-assign a new value to adjust the
.expires property appropriately.