Regular cookies via res.cookie(..., {secure: true})
works, but express-session does not. I made the following to demonstrate:
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
secret: 'qwerqwerqwer',
resave: true,
saveUninitialized: true,
cookie: {
secure: true,
},
}));
app.get('/hello', (req, res) => {
res.cookie('test', 'asdf', {secure: true});
res.send('');
});
const PORT = 7000;
app.listen(PORT, () => {
console.log(`backend listening on port ${PORT}`);
});
When I go to /hello
, there is a Set-Cookie
for test: asdf
but no Set-Cookie
for connect.sid
. In other words, express-session is not sending the cookie at all; it is not a problem on the browser side. I also logged the response headers and it indeed does not include a Set-Cookie
for connect.sid
.
MDN says secure cookies work for localhost. It might not be true for chrome but they said it's true for Firefox, so I downloaded Firefox and tested on it, and I don't receive the connect.sid
cookie, which also confirms that it's express-session
's problem.
I think express-session is overstepping its authority and withholding the cookie for some reason (the secure attribute should be interpreted by the browser anyways). How do I fix this?
CodePudding user response:
Secure cookies are only sent through HTTPS so in development you should add a check to see if you're running on production or locally like bellow:
app.use(session({
secret: 'qwerqwerqwer',
resave: true,
saveUninitialized: true,
cookie: {
secure: process.env.NODE_ENV === "production",
},
}));
CodePudding user response:
I did some more digging and it turns out that this is a known issue with express-session: https://github.com/expressjs/session/issues/837
Basically, the docs around secure cookies has changed. It used to be that the server is supposed to withhold secure cookies over HTTP, and that is what express-session implemented. Now, it has changed to be the client's responsibility.