Authentication using Passport JS

Passport or PassportJS is NodeJS and ExpressJS Compatible middleware for authentication. Passport JS uses different different strategies to authenticate requests. This includes username and password authentication or LocalStrategy, Facebook, Twitter, Apple, github etc authentication and 500+ total strategies.

The purpose to use passport in NodeJS or Express is to authenticate requests by using strategies. Like admin can access all pages, but users are not allowed for certain requests.

Modules required for passport

  1. expressjs
  2. express-session
  3. body-parser
  4. mongoose

Install Passport JS

passport is available on npm as passport. Install passport and include passport in main app through module.

npm i passport

Passport JS is installed in NodeJS Application.


Install Passport Local

Now install passport-local strategy to authenticate username and password.

npm i passport-local

     
       
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

const

Configure Passport

  
const express=require('express');
let app=express();

const User=require('./models/user');
const db=require('./mdb');

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;

app.use(passport.initialize());
app.use(passport.session());

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

passport.use('local', new LocalStrategy((username, password, done) => {
    
    user.find({ username: username }).then(user=>{
      if( user.length==0 ){
          return done(null, null, { message: 'No user found!' });
      }
      else  if (user[0].password !== password) {
          return done(null, null, { message: 'Password is incorrect!' });
      }
      else{
          return done(null, user, null);
      }
      })

  }
));

function isAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
      next();
    } else {
      res.status(403).send('Forbidden');
    }
}
  

Passport Local Authentication Example

Here is a complete example of how to authenticate local in passport. We are using Mongoose for MongoDB Connections in example.

Modules used in local authentication

  1. dotenv
  2. expressjs
  3. express-session
  4. body-parser
  5. nunjucks
  6. mongoose

  require('dotenv').config();
  const express=require("express");
  const path=require("path");
  const nunjucks=require("nunjucks");
  const app=express();
  const session=require('express-session');
  app.set('trust proxy', 1); 
  
  app.use(session({
      secret:"session",
      resave:false,
      saveUninitialized:true,
      cookie:{secure:false}
  }))
  
  const mongoose=require('mongoose');
  const dao=require('./dao');
  const Car=require("./models/car");
  const Admin=require("./models/admin");
  
  const bodyParser=require('body-parser'); 
  app.use(bodyParser.urlencoded({ extended: false })); 
  app.use(bodyParser.json());  
  
  const passport = require('passport');
  const LocalStrategy = require('passport-local').Strategy;
  app.use(passport.initialize());
  app.use(passport.session());
  passport.serializeUser( (user, done)=> {
      done(null, user.id);
    });
  passport.deserializeUser( (user, next)=> {
      next(null, user);
  });
  passport.use( new LocalStrategy({ usernameField: 'name',passwordField:'pass' },(username, password, done) => {
      
      Admin.find({ name: username }).then((err, user) => { 
         
        if (err) { return done(err); }
        if (!user) { return done(null, null, { message: 'No user found!' }); }
        if (user.pass !== password) {return done(null, null, { message: 'Username or password is incorrect!' }) }
  
        return done(null, user, null);


      });


    }
  ));
  function isAuthenticated(req, res, next) {
      if (req.isAuthenticated()) {
        next();
      } else {
        res.status(403).render('login.html',{msg:"Forbidden"});
      }
  }
  
  
  app.use(express.static(path.resolve(__dirname,'public')));
  
  nunjucks.configure(path.resolve(__dirname,'public'),{
       express:app,
       autoscape:true,
       noCache:false,
       watch:true
   });
  
app.get("/",(req,res)=>{
      res.status(200).render("home.html",{name:"Home Page"})  
});
  
  app.get("/addcar",(req,res)=>{
      let carname=new Car({
          _id:mongoose.Types.ObjectId(),
          name:req.query.name,
          brand:req.query.brand,
          type:req.query.type,
          price:req.query.price,
          fuel:req.query.fuel
      });
      carname.save()
      .then(data=>console.log(data))
      .catch(err=>console.warn()err);
  });

  app.get("/login",(req,res)=>{
      res.status(200).render('login.html',{name:"Login"});
  });
  
  app.get('/adminlogin', isAuthenticated, (req, res) => {  res.render('admin-login.html',{name:"admin"}) });
  
  app.get('/logout', (req, res) => { 
      if (req.session) {
          req.session.destroy((err)=> {
            if(err) {
              return next(err);
            } else {
                res.clearCookie('connect.sid');
                req.logout();
                if (!req.user) { 
                    res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
                }
                res.render('login.html',{ msg:"Logout Successfully"});
            }
          });
        }
  });
  app.post("/login",(req,res)=>{
      passport.authenticate('local',  (err, user, info) =>{
          if (err) {
            res.render('login.html', { error: err });
          } 
          else if (!user) {
            res.render('login.html', { errorMessage: info.message });
          } 
          else {
            //setting users in session
            req.logIn(user, function (err) {
              if (err) {
                res.render('login.html', { error: err });
              } else {
                res.render('admin-login.html',{ name:user.name});
               }
            })
          }
        })(req, res);
  });
  
  
   app.get("/**",(req,res)=>{
       res.status(404).render('error.html',{name:"404 - Page not found"})
   })
  
   app.listen(process.env.PORT,()=>{
       console.log(`App running at http://127.0.0.1:${process.env.PORT}`);
   });

Run code

npm start