I am having trouble getting my system to log out with PassportJS. It seems the logout route is being called, but its not removing the session. I want it to return 401, if the user is not logged in in specific route. I call authenticateUser to check if user is logged in.
Thanks a lot!
/******* This in index.js *********/
// setup passport for username & passport authentication
adminToolsSetup.setup(passport);
// admin tool login/logout logic
app.post("/adminTool/login",
passport.authenticate('local', {
successRedirect: '/adminTool/index.html',
failureRedirect: '/',
failureFlash: false })
);
app.get('/adminTool/logout', adminToolsSetup.authenticateUser, function(req, res){
console.log("logging out");
console.log(res.user);
req.logout();
res.redirect('/');
});
// ******* This is in adminToolSetup ********
// Setting up user authentication to be using user name and passport as authentication method,
// this function will fetch the user information from the user name, and compare the password for authentication
exports.setup = function(passport) {
setupLocalStrategy(passport);
setupSerialization(passport);
}
function setupLocalStrategy(passport) {
passport.use(new LocalStrategy(
function(username, password, done) {
console.log('validating user login');
dao.retrieveAdminbyName(username, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
// has password then compare password
var hashedPassword = crypto.createHash('md5').update(password).digest("hex");
if (user.adminPassword != hashedPassword) {
console.log('incorrect password');
return done(null, false, { message: 'Incorrect password.' });
}
console.log('user validated');
return done(null, user);
});
}
));
}
function setupSerialization(passport) {
// serialization
passport.serializeUser(function(user, done) {
console.log("serialize user");
done(null, user.adminId);
});
// de-serialization
passport.deserializeUser(function(id, done) {
dao.retrieveUserById(id, function(err, user) {
console.log("de-serialize user");
done(err, user);
});
});
}
// authenticating the user as needed
exports.authenticateUser = function(req, res, next) {
console.log(req.user);
if (!req.user) {
return res.send("401 unauthorized", 401);
}
next();
}
I was recently having this same issue and none of the answers fixed the issue for me. Could be wrong but it does seem to have to do with a race condition.
Changing the session details to the options below seems to have fixed the issue for me. I have tested it about 10 times or so now and everything seems to be working correctly.
Basically I just changed
saveUninitialized
andresave
fromtrue
tofalse
. That seems to have fixed the issue.Just for reference I'm using the standard
req.logout();
method in my logout path. I'm not using the session destroy like other people have mentioned.Destroying session by yourself looks weird. I faced with this issue having next configuration:
I should say that this configuration works well. The reason of my issue was in custom
sessionStore
that I defined here:To be sure that your issue here too just comment store line and run without session persisting. If it will work you should dig into your custom session store. In my case
set
method was defined wrong. When you usereq.logout()
session storedestroy()
method not invoked as I thought before. Instead invokedset
method with updated session.Good luck, I hope this answer will help you.