Search code examples
node.jsexpresspassport.jspassport-twitter

How to make login persistent in Passportjs node?


I'm using the passport library to handle user's login but am currently faced with a problem. When a user is logged in it doesn't take long before they are logged out again which is a bad UX.

Am I missing something to make user's login persistent?

Here is my code below:

Passport.js

// load all the things we need
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var TwitterStrategy = require('passport-twitter').Strategy;

// include the user model
var User = require('../app/model/user');

// include the auth credentials
var configAuth = require('./auth');


require('../app/model/upload');

module.exports = function(passport) {

  // used to serialize the user for the session
  passport.serializeUser(function(user, done) {
    done(null, user.id);
  });

  // used to deserialize the user
  passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      done(err, user);
    });
  });

  // code for login (use('local-login', new LocalStategy))
  // code for signup (use('local-signup', new LocalStategy))
  // code for facebook (use('facebook', new FacebookStrategy))

  // =========================================================================
  // TWITTER =================================================================
  // =========================================================================
  passport.use(new TwitterStrategy({

      consumerKey: configAuth.twitterAuth.consumerKey,
      consumerSecret: configAuth.twitterAuth.consumerSecret,
      callbackURL: configAuth.twitterAuth.callbackURL,
      userProfileURL: "https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true",
      includeEmail: true,
      profileFields: ['emails']


    },

    function(token, tokenSecret, profile, done) {

      // make the code asynchronous
      // User.findOne won't fire until we have all our data back from Twitter
      process.nextTick(function() {

        User.findOne({
          'member.id': profile.id
        }, function(err, user) {

          // if there is an error, stop everything and return that
          // ie an error connecting to the database
          if (err)
            return done(err);

          // if the user is found then log them in
          if (user) {
            return done(null, user); // user found, return that user
          } else {

            //declare emails as an array

            //var emails = []; 
            // if there is no user, create them
            var newUser = new User();

            newUser.member.id = profile.id;
            newUser.member.token = profile.token;
            newUser.member.username = profile.username;
            newUser.member.displayName = profile.displayName;
            newUser.member.email = profile.emails[0].value;
            newUser.member.medium = 'Twitter';
            newUser.member.picture = profile._json.profile_image_url.replace('_original', '');
            // save  user credentials into the database
            newUser.save(function(err) {
              if (err)
                throw err;
              return done(null, newUser);

              // res.cookie('username', newUser.twitter.username).send('Hello'); 
            });
          }

        });

      });

    }));

};

Some tutorials said I should use passport session which I have used but nothing has changed:

Server.js
//read cookies (needed for auth)
app.use(cookieParser());

// get information from html forms
app.use(bodyParser()); 

//persistent login
app.use(session({ secret: 'keyboard cat' }));

app.use(passport.initialize());

// persistent login sessions
app.use(passport.session()); 

Solution

  • There are two different things here.

    If the User gets logged out after the server is restarted, you need a "store".

    If the User gets logged automatically after some time, even though you didn't restart the server, you need to set an expiry date for the session or the cookie.

    You can use the connect middleware:
    http://www.senchalabs.org/connect/session.html
    .use(connect.session({ secret: 'SUPER SECRET', cookie: { maxAge: 86400000 }}))

    This should keep the session valid for 24 hours (set your own number here)

    OR Theexpress-session middleware: https://github.com/expressjs/session

    Both have a store concept. In a nutshell, it specifies where the details will be stored. If its in memory (not recommended), you will loose the sessions once the server is restarted.