Why is PassportJS in Node not removing session on logout

前端 未结 22 1626
有刺的猬
有刺的猬 2020-11-28 22:11

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 th

相关标签:
22条回答
  • 2020-11-28 23:06

    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

    0 讨论(0)
  • 2020-11-28 23:06

    Apparently there are multiple possible causes of this issue. In my case the problem was wrong order of declarations i.e. the logout endpoint was declared before passport initialization. The right order is:

    app.use(passport.initialize());
    app.use(passport.session());
    
    
    app.get('/logout', function(req, res) {
      req.logout();
      res.redirect('/');
    });
    
    0 讨论(0)
  • 2020-11-28 23:09

    session.destroy may be insufficient, to make sure the user is fully logged out you have to clear session cookie as well.

    The issue here is that if your application is also used as an API for a single page app (not recommended but quite common) then there can be some request(s) being processed by express that started before logout and end after logout. If this were the case then this longer running request will restore the session in redis after it was deleted. And because the browser still has the same cookie the next time you open the page you will be successfully logged in.

    req.session.destroy(function() {
        res.clearCookie('connect.sid');
        res.redirect('/');
    });
    

    That's the what maybe happening otherwise:

    1. Req 1 (any request) is received
    2. Req 1 loads session from redis to memory
    3. Logout req received
    4. Logout req loads session
    5. Logout req destroys session
    6. Logout req sends redirect to the browser (cookie is not removed)
    7. Req 1 completes processing
    8. Req 1 saves the session from memory to redis
    9. User opens the page without login dialog because both the cookie and the session are in place

    Ideally you need to use token authentication for api calls and only use sessions in web app that only loads pages, but even if your web app is only used to obtain api tokens this race condition is still possible.

    0 讨论(0)
  • 2020-11-28 23:09

    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.

    0 讨论(0)
提交回复
热议问题