Today I want to explain a very important concept in Security. Yes, you guess it right.! It's authentication. Let's see how to implement this on our Nodejs Application.

Adding Authentication

Prepare a new sign up page -> get the data (email password) through a post request. Then set up the appropriate routes.

In auth.js controller
exports.postSignup = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

we need to hash (encrypt) the password ->
That’s why we install another very good node package-> bcryptjs
npm install --save bcryptjs

Now let’s configure that. import bcryptjs in the very top of the controller.
const bcrypt = require("bcryptjs");

exports.postSignup = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;
 
  const bcrypt = require("bcryptjs");


  User.findOne({ email: email })
    .then((userdoc) => {
      if (userdoc) {
        console.log("user found");

        return res.redirect("/login");
      }
      bcrypt
        .hash(password, 12)
   
  /*second argument - salt value ( how many rounds hashing will be applied )
    higher the value longer will take. but highly secured */
        .then((hashedPass) => {
          const user = new User({
            email: email,
            password: hashedPass,
            cart: { items: [] },
          });
          return user.save();
        })
        .then((result) => {
          res.redirect("/login");
        });
    })

    .catch((err) => {
      console.log(err);
    });
};

exports.getSignup = (req, res, next) => {
  res.render("auth/signup", {   //auth/signup.ejs
    active: "signup",
    pageTitle: "Signup",
    isAuthenticated: false,
  });
};


sign in


We change the session-id lookup. When there is an active session, let the person access directly. 

in app.js->

app.use((req, res, next) => {
  if (!req.session.user) {
    return next();
  }
  User.findById(req.session.user._id)
    .then((user) => {
      req.user = user;
      next();
    })
    .catch((err) => console.log(err));
});


now in the controller->


exports.postLogin = (req, res, next) => {
  const email = req.body.email;
  const password = req.body.password;

  User.findOne({ email: email })
    .then((userdoc) => {
      if (!userdoc) {
        console.log("user not found");

        return res.redirect("/login");
      }
      bcrypt.compare(password, userdoc.password).then((doMatch) => {
        if (doMatch) {
          req.session.isLoggedIn = true;
          req.session.user = userdoc; // we store user in the session

          return req.session.save((err) => {
            console.log(err);

            res.redirect("/");
          });
        }
        return res.redirect("/login");
      });
    })

    .catch((err) => {
      res.redirect("/login");
      console.log(err);
    });
};


Adding Router Protection

We should be extremely considered about adding route protection. Because if it fails anyone can view details without logging.

if (!req.session.isLoggedIn) {
  return res.redirect('/login')
}

(Look previous tutorial for clearing the session knowledge you have)
add every controller -> routs to this if statement
ex->
exports.getAddProduct = (req, res, next) => {
  if (!req.session.isLoggedIn) {
    return res.redirect("/login");
  }
  res.render("admin/edit-product", {
    pageTitle: "Add Product",
    active: "admin",
    editing: false,
    isAuthenticated: req.session.isLoggedIn, // add for every render call
  });
};




Adding to each and everyone is too difficult... let’s see the better way

The Easy & Better Way

using a middleware to Protect the route.

1st=>add a new middleware as isAuth.js

module.exports = (req, res, next) => {
  if (!req.session.isLoggedIn) {
    return res.redirect("/login");
  }
  next();
};

2nd=> import the middleware

const isAuth = require("../middlewares/is-auth");

3rd=> add it as below in every route for route protection

router.get("/add-product", isAuth, adminController.getAddProduct);

/* The request will travel through left to right
   so isAuth is executed before adminController.getAddProduct middleware
   add every route as this  */

router.get("/edit-product/:productId", isAuth, adminController.getEditProduct);

router.get("/products", isAuth, adminController.getAdminProducts);