Express-Intro to Passport.js part I

Background

Passport is a user authentication library for node. It provides tons of strategies (facebook, google, etc). I’ll be going over the basic passport-local strategy which you sign up with username and passpord. User login with valid name and password.

I’ll also show to how to use session and flash to display error or success message. Also, use express validator to validate user input. Finally encrypt user password with the mighty bcryptjs.

Steps

  1. Install Packages. (bcryptJS, express-validator, passport, psasport-local, etc) You can refer to package.json

  2. Setup User Model with some functions

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    // routes/users.js
    var mongoose = require('mongoose')
    var bcrypt = require('bcryptjs')

    var UserSchema = mongoose.Schema({
    username: { type: String, index: true},
    password: { type: String}
    })

    var User = module.exports = mongoose.model('User', UserSchema)

    module.exports.createUser = function(newUser, callback) {
    bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash(newUser.password, salt, function(err, hash){
    newUser.password = hash
    newUser.save(callback)
    })
    })
    }

    module.exports.getUserByUsername = function(username, callback) {
    var query = { username: username }
    User.findOne(query, callback)
    }

    module.exports.getUserById = function(id, callback) {
    User.findById(id, callback)
    }

    module.exports.comparePassword = function(candidatePassword, hash,callback) {
    bcrypt.compare(candidatePassword, hash, function(err, isMatch) {
    if(err) throw err
    callback(null, isMatch)
    });
    }
  3. Setup mongoDB and passportJS in app.js ( I’m only going over the main imports the basic imports such as express please refer to my github, link below)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var passport = require('passport')
    var LocalStrategy = require('passport-local')
    var mongoose = require('mongoose')
    var flash = require('connect-flash');
    var users = require('./routes/users');


    ...

    mongoose.connect('mongodb://localhost/loginappv2');
    var db = mongoose.connection;

    ...

    app.use(passport.initialize());
    app.use(passport.session());
  4. set up routes in routes/user.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    /* GET users listing. */
    router.get('/signin', function(req, res, next) {
    console.log(res.locals)
    res.render('signin');
    });

    router.post('/signin',
    passport.authenticate('local', {
    successRedirect: '/users/profile',
    failureRedirect: '/users/signin',
    failureFlash: true
    }),
    function(req, res) {
    res.redirect('/users/profile')
    });

    /* GET users listing. */
    router.get('/signup', function(req, res, next) {
    res.render('signup', {errors: ''});
    });

    // Post Sign Up
    router.post('/signup', function(req, res, next) {
    // Parse Info
    var username = req.body.username
    var password = req.body.password

    //Create User
    var newUser = new User({
    username: username,
    password: password
    })
    User.createUser(newUser, function(err, user){
    if(err) throw err;
    })
    res.redirect('/users/signin')
    });

    router.get('/profile', ensureAuthenticated, function(req, res, next) {
    console.log(req.user)
    res.render('profile', {
    user: req.user.username
    });
    });

    router.get('/logout', function(req, res, next) {
    req.logout()
    req.flash('success_msg', 'You are logged out')
    res.redirect('/users/signin')
    })

    module.exports = router;
  5. setup passport and local in routes/user.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// routes/users.js
function ensureAuthenticated(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
req.flash('error_msg', 'you are not logged in')
res.redirect('/users/signin')
}
}

passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err
if(isMatch) {
return done(null, user)
} else {
return done(null, false, {message: 'Invalid password'})
}
})
});
}
));

passport.serializeUser(function(user, done) {
done(null, user.id);
});

passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});

This is part one. I’ll implement flash, session and express validator in next part.