Open In App

Explain passport in Node.js

Last Updated : 14 Dec, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Passport is very easy to integrate NodeJs package, which is used for adding authentication features to our website or web app.

For showing the use of Passport in Nodejs, we are starting with creating a very simple Node app.

Creating a simple Node App using express: 

Step 1: Create a new folder(I have named the folder “NODEAPP”), and create a new file named “Server.js” inside it.

Step 2: Initializing npm using the command “npm init -y”. Package.json file will get added to your project folder.

npm init-y

Command used to initialize npm

Project Structure after running the command “npm init -y”

 Step 3: Install all the necessary packages, i.e, express, body-parser(will be used to fetch HTML form data later), mongoose(used to connect to our MongoDB database), using the command:

npm install express body-parser mongoose

The above command is to be executed to install the required packages.

1 file, named “package-lock.json” will get added to your project structure, and 1 folder named “node_modules” will get added to your project structure after executing the above command.

Project Structure: The final project structure should look like this: 

Final project structure

Step 4: Adding basic code to our Server.js file.

Server.js




// Telling node to include the following
// external modules
var express = require('express');
var app = express();
  
// Mongoose for connecting to our database
const mongoose = require("mongoose");
  
// Body parser to fetch HTML form data later on
const bodyParser = require("body-parser");
  
// Connecting mongoose to our database
// named "userDatabase"
mongoose.connect(
  useNewUrlParser: true,
  useUnifiedTopology: true
});
  
// Handling get request on home route.
app.get("/", function (req, res) {
    res.send("This is the home route");
});
  
// Allowing app to listen on port 3000
app.listen(3000, function () {
    console.log("server started successfully");
})


Step 5: You can also check by opening the browser and typing http://localhost:3000. You should see a white page with the following response.

The response you should get after you type “http://localhost:3000” in your browser.

Creating basic Node app and checking whether everything is fine till now.

 

Step 6: Adding authentication to our website. One simple way to add an authentication feature to our website is taking the email and password input from the user and directly saving them in the database. Similarly, when the user wants to log in, ask for his/her email and password, and if any record matches the entered email and password, then the user is authentic and the login is successful.

Server.js




/*We are going to add simple authentication to our website
We are going to collect data(email and password) entered by
user in the HTML form, created in the INDEX.HTML file, and
we are going to store that data in our database
this is how we can simply register any new user */
  
/* if we want to log in our already registered user, 
then we collect email and password from HTML 
form created in LOGIN.HTML file, and
we can find data(if any) associated with this 
email, and return it to user */
  
var express = require('express');
var app = express();
const bodyParser = require("body-parser");
  
// Allowing app to use body parser
app.use(bodyParser.urlencoded({extended:true}));
  
// Connecting mongoose to our database
// named "userDatabase"
mongoose.connect(
  useNewUrlParser: true,
  useUnifiedTopology: true
});
  
const userSchema = new mongoose.Schema({
  email: String,
  password: String
});
  
// Creating the User model.
const User = new mongoose.model("User", userSchema);
  
  
/* setting a simple get request on the home route, 
and sending our index.html file containing a form 
which will allow user to enter his details and 
register. */
app.get("/", function (req, res) {
  res.sendFile(__dirname + "/index.html");
})
app.get("/login", function(req, res) {
  res.sendFile(__dirname + "/login.html");
})
  
// Handling the post request on /register route.
app.post("/register", function(req, res){
  console.log(req.body);
      
  // Getting the email and password entered
  // by the user
  var email = req.body.username;
  var password = req.body.password;
    
  // Creating a new user with entered credentials.
  var newuser = new User({
    email : email,
    password : password
  })
    
  // Saving the newuser.
  newuser.save();
  console.log("saved successfully");
    
  // Sending the response that user
  // is saved successfully
  res.send("saved successfully");
})
  
APP.post("/login", function(req, res) {
    console.log(req.body);
       
    // Getting the email and password entered
    // by the user
    var emailEntered = req.body.username;
    var passwordEntered = req.body.password;
      
    // Checking if the email entered exists
    // in database or not.
    User.findOne({email : emailEntered}, 
                 function(err, data){
       if(data) {
  
           // The email exists in the database.
           console.log(data);
              
           /* checking if the password entered 
           is matching the original password */
           if(data.password == passwordEntered){
               res.send("login successful!");
           }
           else {
  
               // Password is incorrect.
               res.send("Incorrect Password");
            }
       }
       else {
  
           // The email does not exist in the database
           console.log(err);
       }
    });
})
  
// Allowing app to listen on port 3000
app.listen(3000, function () {
  console.log("server started successfully");
})


Index.html




<!DOCTYPE html>
<html>
  
<head>
    <title>Page Title</title>
</head>
  
<body>
    <form class="" action="/register" 
          method="post">
        <input type="email" name="username" 
               placeholder="Name" value="">
        <input type="password" name="password" 
               placeholder="Password" value="">
        <button type="submit" name="button">
            Submit
        </button>
    </form>
</body>
  
</html>


Login.html




<!DOCTYPE html>
<html lang="en" dir="ltr">
  
<head>
    <meta charset="utf-8">
    <title></title>
</head>
  
<body>
    <form class="" action="/login" method="post">
        <input type="email" name="username" 
               placeholder="Name" value="">
        <input type="password" name="password" 
               placeholder="Password" value="">
        <button type="submit" name="button">
            Submit
        </button>
    </form>
</body>
  
</html>


But there are a few limitations in using this simple method of authentication.

  • The passwords entered by the user in the registering process are left exposed to everyone in the database, i.e., anyone in the organization who has the access to the database can see any user’s password. But, the passwords cannot be left exposed and we need strong encryption so that we can store our passwords safely in the database.

The password is exposed to everyone who is looking into the database.

  • Every time(maybe 20-25 times each day or even more than that) we want to use this web app or website, we have to re-enter our email and password, which becomes very time-consuming.
  • We can not add social networking sign-in feature using this simple authentication code.

Passport eliminates all of these limitations for us. If we use Passport, then: 

  • We don’t have to leave our passwords exposed. The whole encryption and decryption procedure is done by Passport including the hashing and encrypting of passwords.
  • Passport allows us to create and maintain sessions. For example, when you visit any social media website or mobile app, you do not have to log in, again and again, each time you want to use Instagram or Facebook. Rather, the information is saved, which means you don’t have to log in each time you want to use the website. In technical words, a session has been created, and it will be maintained for the next few days, or a few weeks, or a few months.
  • Passport also allows us to easily integrate authentication using Google, Facebook, LinkedIn, and various other social networking services.

Step 7: For using passport, we have to install 4 npm packages, namely “passport“, “passport-local“, “passport-local-mongoose” and “express-session“(make sure that you download “express-session” and not “express-sessions”).

In the command line, write the following command to install all the four packages: 

npm install passport passport-local passport-local-mongoose express-session

Following command will install the required packages.

Once you have installed, you need to add the following code at the top of the Server.js file to include the passport module.

Server.js




const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
  
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended:true}));
  
// Below all the app.use methods
app.use(session({
    secret : "any long secret key",
    resave : false,
    saveUninitialized : false
}));


Step 8: Initializing Passport and starting the Session. For initializing Passport and starting the session, write the following code just below the session declaration code.

Server.js




app.use(session({
  secret: "any long secret key",
  resave: false,
  saveUninitialized: false
}));
  
// Initializing Passport
app.use(passport.initialize());
  
// Starting the session
app.use(passport.session());
  
// Creating user schema and adding a plugin to it
  
const userSchema = new mongoose.Schema({
  email: String,
  password: String
});
userSchema.plugin(passportLocalMongoose);


Step 9: Now, we want that we remain logged in for some time even if we close the browser window, i.e., we want a session to be established. The session uses a Cookie to store the data and messages and allows the server to provide correct session data to the User. Process of creating Cookies and storing messages into it: Serializing Process of crumbling Cookies and extracting messages from the Cookies so that right data should be served to user: 

Server.js




const User = new mongoose.model("User", userSchema);
passport.use(User.createStrategy());
  
// Serializing and deserializing
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());


Step 10: Now, we are all set to add authentication to our website. We had installed the required packages, configured the session, initialized Passport and session, and told passport to use and manage cookies.

Handling the get requests:

Server.js




// Handling get request on the home and login route
app.get("/", function (req, res) {
  
  /* req.isAuthentcated() returns true or 
  false depending upon whether a session 
  is already running or not.*/
  if(req.isAuthenticated()) {
   
    /* if the request is already authenticated, 
    i.e. the user has already logged in and 
    there is no need to login again. Or we 
    can say, the session is running. */  
    res.send("
     You have already logged in. No need to login again");
  }
    
  else{
  
    // If the user is new and no session
    // is Running already 
    res.sendFile(__dirname + "/index.html");
  }
})
  
// Handling get request on login route
app.get("/login", function(req, res) {
    if(req.isAuthenticated()){
        /* if request is already authenticated, 
        i.e. user has already logged in and 
        there is no need to login again. */ 
        res.send("
You have already logged in. No need to login again");
     }
     else{
       res.sendFile(__dirname + "/login.html");
   }
})


Step 11: Now, in the register route, we have to add simple code that will allow us to register any new user.

Server.js




/* The index.html file will be same as that
used in the earlier method of authentication*/ 
app.post("/register", function(req, res){
  console.log(req.body);
    
  // Getting Email and PAssword Entered by user
  var email = req.body.username;
  var password = req.body.password;
    
  /* Registering the user with email and
  password in our database  
  and the model used is "User" */
  User.register({ username : email }, 
  req.body.password, function (err, user) {      
    if (err) {
      
      // if some error is occurring, log that error
      console.log(err);
    }
    else {
      passport.authenticate("local")
      (req, res, function() {
        res.send("successfully saved!"); 
      })
    }
  })
})


And the similar code is to handle login requests. Following is the code for handling the post request on the /login route.(The login.html file will be the same as that used in the earlier method of authentication )

Server.js




// All handling related to login is done below.
// Here we are handling the post request on
// /login route
app.post("/login", function (req, res) {
  console.log(req.body);
  
  const userToBeChecked = new User({
    username: req.body.username,
    password: req.body.password,
  });
  
  // Checking if user if correct or not
  req.login(userToBeChecked, function (err) {
    if (err) {
  
      console.log(err);
        
      // If authentication fails, then coming
      // back to login.html page
      res.redirect("/login");
    } else {
      passport.authenticate("local")(
        req, res, function () {
        User.find({ email: req.user.username }, 
          function (err, docs) {
          if (err) {
            console.log(err);
          } else {
            //login is successful
            console.log("credentials are correct");
            res.send("login successful");
          }
        });
      });
    }
  });
});


You just have to install all the packages, write the following code, start the server(using “node server.js/node app.js” command) and you are ready to Authenticate your Users using Passport.

Index.html




<!DOCTYPE html>
<html>
  
<head>
    <title>Page Title</title>
</head>
  
<body>
    <h1>REGISTER</h1>
    <form class="" action="/register" method="post">
        <input type="email" name="username" 
               placeholder="Name" value="">
        <input type="password" name="password" 
               placeholder="Password" value="">
        <button type="submit" name="button">
            Submit
        </button>
    </form>
</body>
  
</html>


Login.html




<!DOCTYPE html>
<html lang="en" dir="ltr">
  
<head>
    <meta charset="utf-8">
    <title></title>
</head>
  
<body>
    <h1>LOGIN</h1>
    <form class="" action="/login" method="post">
        <input type="email" name="username" 
               placeholder="Name" value="">
        <input type="password" name="password"
               placeholder="Password" value="">
        <button type="submit" name="button">
            Submit
        </button>
    </form>
</body>
  
</html>


Server.js




var express = require('express');
var app = express();
const mongoose = require("mongoose");
   
/* Requiring body-parser package  
to fetch the data that is entered 
by the user in the HTML form.*/
const bodyParser = require("body-parser");
   
// Telling our Node app to include all these modules
const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = 
       require("passport-local-mongoose");
   
// Allowing app to use body parser
app.use(bodyParser.urlencoded({ extended: true }));
   
app.use(session({
    secret: "long secret key",
    resave: false,
    saveUninitialized: false
}));
   
// Initializing Passport
app.use(passport.initialize());
  
// Starting the session
app.use(passport.session());
   
// Connecting mongoose to our database 
mongoose.connect(
    useNewUrlParser: true,
    useUnifiedTopology: true
}); 
   
/* Creating the schema of user which now 
include only email and password for 
simplicity.*/
const userSchema = new mongoose.Schema({
    email: String,
    password: String
});
   
/* Just after the creation of userSchema, 
we add passportLocalMongoose plugin 
to our Schema */
userSchema.plugin(passportLocalMongoose);
   
// Creating the User model
const User = new mongoose.model("User", userSchema);
   
/* After the creation of mongoose model, 
we have to write the following code */
passport.use(User.createStrategy());
   
// Serializing and deserializing
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
   
// Handling get request on the home route
app.get("/", function (req, res) {
  
    /* req.isAuthentcated() returns true or 
    false depending upon whether a session is 
    already running or not. */
    if (req.isAuthenticated()) {
   
        /* if request is already authenticated, 
        i.e. user has already logged in and 
        there is no need to login again or 
        we can say, session is running.*/
        res.send(
"You have already logged in. No need to login again");
    }
   
    else {
  
        // If the user is new and 
        // no session is Running already
        res.sendFile(__dirname + "/index.html");
    }
})
   
   
// Handling get request on login route
app.get("/login", function (req, res) {
    if (req.isAuthenticated()) {
  
        /* If request is already authenticated, 
        i.e. user has already logged in and 
        there is no need to login again. */
        res.send(
"You have already logged in. No need to login again");
    }
    else {
   
        /* if session has expired, then user 
         need to login back again and 
         we will send the Login.html */
        res.sendFile(__dirname + "/login.html");
    }
})
   
/* Registering the user for the first time
handling the post request on /register route.*/
app.post("/register", function (req, res) {
    console.log(req.body);
    var email = req.body.username;
    var password = req.body.password;
    User.register({ username: email },
        req.body.password, function (err, user) {
            if (err) {
                console.log(err);
            }
            else {
                passport.authenticate("local")
                 (req, res, function () {
                    res.send("successfully saved!");
                })
            }
        })
})
   
// Handling the post request on /login route
app.post("/login", function (req, res) {
    console.log(req.body);
  
    const userToBeChecked = new User({
        username: req.body.username,
        password: req.body.password
    });
   
    // Checking if user if correct or not
    req.login(userToBeChecked, function (err) {
        if (err) {
            console.log(err);
            res.redirect("/login");
        }
        else {
            passport.authenticate("local")
                (req, res,function () {
                User.find({ email: req.user.username },
                    function (err, docs) {
                      if (err) {
                         console.log(err);
                      }
                     else {
  
                       //login is successful
                       console.log("credentials are correct");
                     res.send("login successful");
                        }
                    });
            });
        }
    })
})
   
// Allowing app to listen on port 3000
app.listen(3000, function () {
    console.log("server started successfully");
})


Using this code and adding authentication using Passport, we have eliminated the three major problems: 

  • Once we login, a session is created. This means whenever we open the site again, we need not to log in once more. Cookies got stored in the browser(when you logged in for the first time) and they will be used as and when you come back again. (req.isAuthenticated() checks whether a session is already running or not).
  • Our Users’ Passwords are safe. They are not left exposed in our database. We have delegated all the encryption/decryption task to Passport and that’s it.

Passwords are encrypted and are not visible to anyone.

  • We can see that now, there is no column for “password”. Our passwords are encrypted by Passport. And whenever they are needed for log in purpose, Passport can again decrypt the passwords and use them.
  • We can also add authentication using Google, Facebook, LinkedIn, and various other Social Networking Services using Passport only.(We have not discussed it here but the code is similar to this)

Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads