Reputation: 5794
Update at bottom!
My node.js server uses express.js to manage sessions. Upon login, I store some user information in req.session. I have a logout endpoint that simply deletes the user data from req.session before sending its response.
With every request the user makes, I use authentication middleware to make sure there is still user data in the session, so deleting user data in the session object should fail any subsequent authentication.
To test my server, I have a nodeunit test that logs in, calls a few endpoints, logs out, and then attempts to call another endpoint. I would expect the last endpoint to fail in authentication because I previously blew away user data. Instead, when I make the last call, my user data is still there. It's as if the logout call that deleted it was not written back into the session store.
Here's my app.js:
app.use(express.cookieParser('secretPassword'));
app.use(express.cookieSession({key: 'someKey'}));
...
app.get('/logout', accounts.logout);
app.get('/account', auth.authenticateSession, accounts.show);
auth.js:
exports.authenticateSession = function(req, res, next) {
if (!req.session.user) {
return res.json(401, {
error: 'Access denied. You must be logged in to make this request.'
});
}
...
}
accounts.js:logout:
exports.logout = function(req, res) {
req.session.user = null;
res.send('Logged out');
};
Unit tests:
step1_logIn : function(test) {
var postData = qs.stringify({
accountname: 'testAcct',
accountpassword: 'hello'
});
ct.postAndCall('/login', null, postData, function(resData, res) {
myCookie = res.headers['set-cookie'];
test.ok(res.statusCode === 200);
test.done();
});
},
step2_logout : function(test) {
ct.getAndCall('/logout', myCookie, function(data, res) {
test.ok(data === 'Logged out.');
test.ok(res.statusCode === 200);
test.done();
});
},
step3_ensureLoggedOut: function(test) {
ct.getAndCall('/account', myCookie, function(data, res) {
test.ok(res.statusCode === 401);
test.done();
});
}
When the tests run, execution goes through logout successfully, then into authenticateSession
on the call to /account
and at this point, req.session.user
still exists! Why!?
Update:
It looks like this problem is directly related to the app middleware surrounding cookies. When I use app.use(express.session())
instead of app.use(express.cookieSession(...))
, the session data is properly blown away and my tests pass.
Upvotes: 1
Views: 1026
Reputation: 5794
I figured it out. Apparently express.cookieSession(...)
is meant to be a set-once type of storage. Subsequent requests will have access to the session data that was initially set, but changing the req.session object won't save back new session data.
To fix the problem, I switched over to use express.session(...)
which uses a server-side store for session vars.
Upvotes: 1