Farid
Farid

Reputation: 1665

Passport 'logout()' not working as expected

I have a simple authentication system where a user may log in, then log out.

I have many pages and many routes in my app, and every route has this general structure (I'm using my dashboard.hbs route here as an example):

router.get('/dashboard', ensureAuthenticated, function(req, res, next) {
  User.findOne({ username: req.user.username }, function(err, loggedInUser) {
    if (err) throw err
    else {
      res.render('dashboard', {
        user: loggedInUser
      })
    }
  })
});

Specifically, I'm assigning loggedInUser to user to use in my dashboard.hbs partial like so:

<h2 align="center">{{user.first_name}}'s Dashboard</h2>

When logging out, I simply use the '/logout route like so:

router.get('/logout', function(req, res, next) {
    req.logout()
    res.render('logout')
});

The problem with this approach is that I'm repeating user: loggedInUser in every route, and I'd like to refactor my code to DRY it up, and define the user that's logged in just once, and use that in every partial.

To help solve this problem, I did the following in my server.js file:

app.use(function (req, res, next) {
  res.locals.logged_in_user = req.user
  next();
});

Now, I'm able to use logged_in_user in any partial without having to assign it in a route. This works fine everywhere, except when logging out. When logging out, the req.user property (assigned as logged_in_user) is not immediately removed, and the login session is not immediately cleared. I'm running the following code:

router.get('/logout', function(req, res, next) {
    req.logout()
    res.render('logout')
});

This is almost identical to the Passport documentation here.

Once I hit the /logout route, I have to refresh the page for the login session to be cleared. This was not the case when I was using user: loggedInUser in every route. Now that it's refactored, it no longer works properly.

I should also note that my layout.hbs file includes this code:

<ul class="nav nav-pills pull-right">
  {{#if logged_in_user }}
    <li role="presentation"><a href="/dashboard">Dashboard</a></li>
    <li role="presentation"><a href="/logout">Log Out</a></li>
    <li role="presentation"><a href="/messages">Messages</a></li>
     <li role="presentation"><a href="/users/member">Profile</a></li>
  {{else}}
    <li role="presentation"><a href="/login">Login</a></li>
    <li role="presentation"><a href="/register">Register</a></li>
  {{/if}}
</ul>

Using the refactored style, how do I clear a user's login session?

Update

While res.render('logout') does not seem to work, I can just res.redirect the user to the login page, and display a message across the page (using connect-flash) that they have successfully logged out.

Upvotes: 0

Views: 758

Answers (1)

robertklep
robertklep

Reputation: 203286

Calling req.logout() will clear req.user (it does req.user = null, basically), but your middleware created a reference to the original object, which is what res.locals.logged_in_user is still pointing to.

As for the session (req.session.user): that will be updated at the end of the response, so after res.render('logout') has been called. That's why using res.redirect() is a better way to clear the session after logging out.

Upvotes: 1

Related Questions