Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Staying authenticated after the page is refreshed using Passportjs

I am building a SPA using express, mongoose and passportjs.

I have created a simple schema for my user:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');

var User = new Schema({
    username: String,
    password: String,
    first_name: String
}, { collection: 'users' });

User.plugin(passportLocalMongoose);

mongoose.model('User', User);

Configured passport using the User object which mongoose gave me:

passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());         
passport.deserializeUser(User.deserializeUser());

And configured my app to authenticate the user when navigating to this route:

app.post('/login', passport.authenticate('local'), function(req, res, next) {
    if (req.isAuthenticated()) {
        return res.json({ state: 'success', user: { first_name: req.user.first_name } });    
    }
    return res.json({ state: 'failure', message: 'cannot authenticate' });
});

Now I am able to successfully authenticate a user. And the browser saves a session id cookie.

My problem is that every time the user refreshes the page passport won't deserialize the user using the session id, what makes the user unauthenticated.

While accessing the req.user object in the site's root I get undefined what make me realize passport doesn't deserialize the user properly:

app.use('/', function (req, res, next) {
    console.log(req.user); // prints undefined.        

    next();
});

What is the proper way for restoring a user after refreshing the page?

like image 701
Matan Givoni Avatar asked Sep 28 '22 06:09

Matan Givoni


1 Answers

The solution is to store the sessions in the DB. I used connect-mongo.

app.js:

var mongoose = require('mongoose');
var expressSession = require('express-session');
var MongoStore = require('connect-mongo')(expressSession);

mongoose.connect(db_url, function (err) {
    if (err) {
        console.log(err);
    }
});

app.use(expressSession({
    secret: process.env.SESSION_SECRET || 'keyboard cat',
    resave: false,
    saveUninitialized: false,
    store: new MongoStore({ mongooseConnection: mongoose.connection })
}));

after this, req.isAuthenticated() returns true on every request even after refreshing the page. (Thanks to app.use(passport.session()) which comes before any route handler)

app.use('/', function (req, res, next) {
    if (req.isAuthenticated()) {
        // returns true if a user already logged in.
    }
    next();
});
like image 71
Matan Givoni Avatar answered Oct 05 '22 06:10

Matan Givoni