I’m using NodeJS an express session handling with Redis. Here is the interesting part:
let session = require('express-session')
let cookieParser = require('cookie-parser')
let Redis = require('ioredis');
let clientRedis = new Redis();
let RedisStore = require('connect-redis')(session);
const SESSIONSECRET = require(config.get('app.secretsession')).secret;
app.use(cookieParser(SESSIONSECRET));
const sessionMiddleware = session({
store: new RedisStore({
client: clientRedis,
}),
secret: SESSIONSECRET,
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 30000,
secure: false,
httpOnly: true,
domain: config.get('app.domainecookie')
}
});
app.use(sessionMiddleware);
I’m making periodically calls to my server, and I see the "expires" parameter of my cookie updates correctly, pushing the 30000 limit further.
But, for some reason, the session is destroyed and I get another session ID, again for 30000.
Here is what I use to check my session ID:
app.use((req, res, next) => {
console.log(`CURRENT SESSION: ${req.session.id}`);
})
When I check in my browser, I see that even if the cookie expiration date changes on the server, it doesn’t change in the client (browser). Is there a way to update the expiration date client-side?
I thought I could resend the cookie like this:
app.use((req, res, next) => {
console.log(`CURRENT SESSION: ${req.session.id}`);
res.cookie('connect.sid', req.sessionID, req.session.cookie);
})
But it keeps changing the cookie to another one, sometimes with the value of a correct sessionID, sometimes with ‘s:’ followed by a value of another cookie.
I thought I could send the ‘connect.sid’ cookie from my client to the server to update it, but as it’s a signed cookie I would have to use the same secret client-side and that is clearly not possible.
What am I doing wrong here? I thought setting "resave" to true wouldn’t destroy the session.
2
Answers
Waw, that was not as easy as it should be. I finally found what to do: the problem was I had to sign the cookie with the same secret as I initialized it. For that, I had to install the
cookie-signature
package.I create a signature function like this:
Then, in my middleware
app.use
function, I simply had to write these lines (look at thes:
which is added for some reason...):Like this, the expiration date of the cookie client-side is pushed further, like it is in the server-side.
Note: it's very strange that the
connect.sid
cookie doesn't update automatically client-side even though it has been updated server-side. I don't see the point of usingresave: true
if the information is not passed to the client. If I misread the documentation and there is actually a native way to do it, I'd be glad to know the way.If you want to handle your user’ session with a cookie, using express-session and connect-redis, you can normally follow this example
The node-session already parse the cookies, so you don’t need an other package for it. It also put everything in the response header automatically, so no need to set the res.cookie yourself.
EDIT : I was a bit hasty, the express-session does not give you the cookies. It parse them but does not give you the cookies on the request object. You should still use cookie-parser package, if you are interest in other cookies than the session cookie
You don’t have anything else to do from what I can tell.
The TTL of the key in redis will be reset/update at the max age of the cookie, here 1 minute, and you should see the expiration date of the cookie update in the browser too.
Maybe the custom middleware you made hijacked the cookie value send in the response
Tell me if it helps you. If something still feels strange to you, tell me in comment and I will update my response.
Cheers !