Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Authentication in NodeJS using Passport

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 513
    Comment on it

    Authentication is a mechanism of verifying users coming to particular system so that they can only make use of resources for which they have been provided permission. Having a strong authentication mechanism in an important part of a system.

     

    Thus in order to save developer from taking all the pain for developing authentication module Node.js provide us with a very robust and powerful middleware known as Passport which take care of all our authentication concerns.

     

    Acting a middleware Passport does an excellent job by separating other modules of application from authentication module. Passport can be very easily configured with application being built on Express.

     

    For authentication Passport have a long list of mechanism as per Passport documentation there are more then 140+ authentication mechanisms we can choose from. User can be authenticated against a local/remote database or single sign-on using OAuth providers for Facebook,Twitter etc. If you want to make use of Passport for authentication using facebook,google etc you need to install library being provided by individual social-media.

     

    For this tutorial we are using local storage so we will start with installing Passport first

    npm install passport

     

    As we are going for local authentication against value stored in our database we need to install  passport-local module:

     

    npm install passport-local

     

    Before moving ahead with the tutorial make sure all these are added to package.json as local dependencies :

     

    "passport": "~0.2.0",
    "passport-local": "~1.0.0"

     

    Configuring Passport With Express

     

    As passport only provide us with mechanism to handle authentication , thus for handling session we would require other module know as  express-session . To install module type :

     

    npm install --save express-session

     

    To attach passport with express open app.js and add the following code :

    // Configuring Passport
    var passport = require('passport');
    var expressSession = require('express-session');
    app.use(expressSession({secret: 'mySecretKey'}));
    app.use(passport.initialize());
    app.use(passport.session());

     

    Serializing and Deserializing User Instances

     

    While making use of passport we also need to serialize and deserialize user instance from a session store in order to support login sessions, so that every subsequent request will not contain the user credentials. Passport provide us with two inbuilt methods for the same serializeUser and deserializeUser :

     

    passport.serializeUser(function(user, done) {
      done(null, user._id);
    });
     
    passport.deserializeUser(function(id, done) {
      User.findById(id, function(err, user) {
        done(err, user);
      });
    });

     

    Using Passport for Login and SignUp :

     

    Now we will be making use of passport strategies for handling login and signup , each of these will make use of Local Authentication Strategy of passport making use of

     

    passport.use()

     

    Making use of passport login would look something like this :

     

    passport.use('login', new LocalStrategy({
        passReqToCallback : true
      },
      function(req, username, password, done) {
        // check in mongo if a user with username exists or not
        User.findOne({ 'username' :  username },
          function(err, user) {
            // In case of any error, return using the done method
            if (err)
              return done(err);
            // Username does not exist, log error & redirect back
            if (!user){
              console.log('User Not Found with username '+username);
              return done(null, false,
                    req.flash('message', 'User Not found.'));                 
            }
            // User exists but wrong password, log the error
            if (!isValidPassword(user, password)){
              console.log('Invalid Password');
              return done(null, false,
                  req.flash('message', 'Invalid Password'));
            }
            // User and password both match, return user from
            // done method which will be treated like success
            return done(null, user);
          }
        );
    }));

     

    The first parameter to passport.use() is the name of the strategy . The second parameter is the type of strategy that you want to create i.e LocalStrategy.

     

    Using passport for registration would look something like this :

     

    passport.use('signup', new LocalStrategy({
        passReqToCallback : true
      },
      function(req, username, password, done) {
        findOrCreateUser = function(){
          // find a user in Mongo with provided username
          User.findOne({'username':username},function(err, user) {
            // In case of any error return
            if (err){
              console.log('Error in SignUp: '+err);
              return done(err);
            }
            // already exists
            if (user) {
              console.log('User already exists');
              return done(null, false,
                 req.flash('message','User Already Exists'));
            } else {
              // if there is no user with that email
              // create the user
              var newUser = new User();
              // set the user's local credentials
              newUser.username = username;
              newUser.password = createHash(password);
              newUser.email = req.param('email');
              newUser.firstName = req.param('firstName');
              newUser.lastName = req.param('lastName');
     
              // save the user
              newUser.save(function(err) {
                if (err){
                  console.log('Error in Saving user: '+err);  
                  throw err;  
                }
                console.log('User Registration succesful');    
                return done(null, newUser);
              });
            }
          });
        };
         
        // Delay the execution of findOrCreateUser and execute
        // the method in the next tick of the event loop
        process.nextTick(findOrCreateUser);
      });
    );

     

    Once login and registration logic is done we will make changes in our routes to make use of passport :

     

    module.exports = function(passport){
     
      /* GET login page. */
      router.get('/', function(req, res) {
        // Display the Login page with any flash message, if any
        res.render('index', { message: req.flash('message') });
      });
     
      /* Handle Login POST */
      router.post('/login', passport.authenticate('login', {
        successRedirect: '/home',
        failureRedirect: '/',
        failureFlash : true
      }));
     
      /* GET Registration Page */
      router.get('/signup', function(req, res){
        res.render('register',{message: req.flash('message')});
      });
     
      /* Handle Registration POST */
      router.post('/signup', passport.authenticate('signup', {
        successRedirect: '/home',
        failureRedirect: '/signup',
        failureFlash : true
      }));
     
      return router;
    }
    
    

     

    The most important thing to note over here is passport.authenticate() to delegate the authentication to login and signup strategies .

     

    Beside this passport also provide you mechanism for protecting routes i.e if a particular user is restricted to visit home page without authentication , he will be redirected to some other page :

     

    /* GET Home Page */
    router.get('/home', isAuthenticated, function(req, res){
      res.render('home', { user: req.user });
    });
     
    // As with any middleware it is quintessential to call next()
    // if the user is authenticated
    var isAuthenticated = function (req, res, next) {
      if (req.isAuthenticated())
        return next();
      res.redirect('/');
    }

     

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: