Why is PassportJS in Node not removing session on

2020-01-26 03:35发布

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();
}

20条回答
Ridiculous、
2楼-- · 2020-01-26 04:03

You shoulde be using req.logout() to destroy the session in the browser.

app.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/'); // whatever the route to your default page is
});
查看更多
地球回转人心会变
3楼-- · 2020-01-26 04:04

I was having the same issue. Turned out that my version of passport wasn't compatible with Express 4.0. Just need to install an older version.

    npm install --save express@3.0.0
查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-01-26 04:05

All examples here do a redirect after the req.session.destroy. But do realise that Express will create a new session instantly for the page you are redirecting to. In combination with Postman I found the strange behaviour that doing a Passport-Login right after the logout gives the effect that Passport is successful but cannot store the user id to the session file. The reason is that Postman needs to update the cookie in all requests for this group, and this takes a while. Also the redirect in the callback of the destroy does not help.

I solved it by not doing a redirect but just returning a json message.

查看更多
贪生不怕死
5楼-- · 2020-01-26 04:06

I got an experience that, sometime it's doesn't work because you fail to to setup passport properly. For example, I do vhost, but on main app I setup passport like this which is wrong.

app.js (why wrong ? please see blockqoute below)

require('./modules/middleware.bodyparser')(app);
require('./modules/middleware.passport')(app);
require('./modules/middleware.session')(app);
require('./modules/app.config.default.js')(app, express);

// default router across domain
app.use('/login', require('./controllers/loginController'));
app.get('/logout', function (req, res) {
    req.logout();
    res.redirect('/');
});

// vhost setup
app.use(vhost('sub1.somehost.dev', require('./app.host.sub1.js')));
app.use(vhost('somehost.dev', require('./app.host.main.js')));

actually, it must not be able to login, but I manage to do that because, I continue to do more mistake. by putting another passport setup here, so session form app.js available to app.host.sub1.js

app.host.sub1.js

// default app configuration
require('./modules/middleware.passport')(app);
require('./modules/app.config.default.js')(app, express);

So, when I want to logout... it's not work because app.js was do something wrong by start initialize passport.js before express-session.js, which is wrong !!.

However, this code can solved the issues anyway as others mention.

app.js

app.get('/logout', function (req, res) {
    req.logout();
    req.session.destroy(function (err) {
        if (err) {
            return next(err);
        }

        // destroy session data
        req.session = null;

        // redirect to homepage
        res.redirect('/');
    });
});

But in my case the correct way is... swap the express-session.js before passport.js

document also mention

Note that enabling session support is entirely optional, though it is recommended for most applications. If enabled, be sure to use express.session() before passport.session() to ensure that the login session is restored in the correct order.

So, resolved logout issue on my case by..

app.js

require('./modules/middleware.bodyparser')(app);
require('./modules/middleware.session')(app);
require('./modules/middleware.passport')(app);
require('./modules/app.config.default.js')(app, express);


// default router across domain
app.use('/login', require('./controllers/loginController'));
app.get('/logout', function (req, res) {
    req.logout();
    res.redirect('/');
});

app.host.sub1.js

// default app configuration
require('./modules/app.config.default.js')(app, express);

and now req.logout(); is work now.

查看更多
beautiful°
6楼-- · 2020-01-26 04:06

Since you are using passport authentication which uses it's own session via the connect.sid cookie this simplest way of dealing with logging out is letting passport handle the session.

app.get('/logout', function(req, res){
  if (req.isAuthenticated()) {
    req.logOut()
    return res.redirect('/') // Handle valid logout
  }

  return res.status(401) // Handle unauthenticated response
})
查看更多
放荡不羁爱自由
7楼-- · 2020-01-26 04:08

This worked for me:

app.get('/user', restrictRoute, function (req, res) {
  res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate,
              max-stale=0, post-check=0, pre-check=0');
});

It makes sure that your page won't get stored in cache

查看更多
登录 后发表回答