Cookie expiration date not being set correctly
See original GitHub issueI originally opened this issue in the connect-redis
repo (https://github.com/tj/connect-redis/issues/292), and it was suggested the issue be raised upstream to express-session
.
When rolling
and resave
are set to false, and when the session is modified, the Expires
date on the Set-Cookie
header is set to the current date + maxAge
, which causes the age of the session cookie to live beyond the life of the original session (as determined by maxAge
).
In other words, when rolling is disabled, the life of the cookie is being extended by maxAge
each time the session data changes. The expected behavior (I believe) is that, even when the session data is modified, the session length should never exceed maxAge
from the time the session was first created.
This is causing connect-redis
to break because the cookie set by express-session
is living beyond the length of the maxAge
of the original session.
This is happening with the latest version of express-session and connect-redis, Node 10.16.0. Please see https://github.com/tj/connect-redis/issues/292 for a information / discussion of the issue. Sample code showing our configuration when the issue happens:
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');
const redisClient = redis.createClient(...);
const store = new RedisStore({ client: redisClient });
app.use(
session({
secret: 'secret here',
store: store,
resave: false,
rolling: false,
saveUninitialized: false,
proxy: true,
name: 'xyz',
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 14,
path: '/',
secure: true,
httpOnly: true,
},
});
);
Issue Analytics
- State:
- Created 4 years ago
- Comments:19 (10 by maintainers)
Top GitHub Comments
The issue began when upgrading
connect-redis
from3.4.2
to4.0.3
.The issue starts to happen when modifying the session
maxAge
after the initial session was created.connect-redis
attempts to save the modified session and (I’m guessing) calculates the TTL of the redis record as “currentTime - sessionCreationDate” which results in a negative TTL. Since TTL should always be positive, Redis throwsERR invalid expire time in set
.One thing I found particularly strange is that
console.log(req.session.cookie._expires)
will print the date the session was first created (for example, December 14th), but in theSet-Cookie
header the actualExpires
date is the current time the response was served (for example, December 16th). Not sure if it’s expected thatreq.session.cookie._expires
does not match theExpires
date inSet-Cookie
.Well, I mean, my guess would be that the store would (at least by default) simply set the data expiration time to
currentDate + maxAge
whenever there is a.save()
or a.touch()
, with the.touch()
being a signal that only the expiration should be updated (if the store desires to do so). That should be just a TTL set on the existing key for Redis, I would guess. It is possible to set up some method where both the cookie and the session could share the exact same expiration, but I’m not sure if that’s truly desired in the long run. The biggest downside is that the store needs to “peek” into the session data in order to just work… but yes, there is no way for the store to otherwise know what the user configured themaxAge
to in this module, so I think maybe that’s where this pattern came from.Really, some of the interface between the store and this module (“manager”?) does need to be overhauled for a 2.x. I believe there is already a request out there such that this module could inform the store of what settings were used for reference (things like
maxAge
), but it needs some more though in what the interface would look like when the same store is supplied to more than one “manager” with different TTLs (perhaps an anonymous section vs a logged in section, idk).