DEV Community

NJOKU SAMSON EBERE
NJOKU SAMSON EBERE

Posted on • Edited on

Authentication with Nodejs and mongoDB - Part 3

This is the third part of this authentication series with nodejs and mongoDB. If you have not checked out the previous parts, please check out part 1 and part 2.

In this part of the tutorial, we will be covering the login with jasonwebtoken (JWT). By the end, we will have seen how to crosscheck users and match the hashed password to the plain text password.

Without wasting anytime, let's jump into it.

Starter Project

If you are not coming from the previous tutorial, then you can get the starter project from here

Login Endpoint

  • Install JWT

npm i jsonwebtoken -s

Enter fullscreen mode Exit fullscreen mode
  • Import JWT just below the const bcrypt = require("bcrypt"); line at the top of the app.js file like so:

const jwt = require("jsonwebtoken");

Enter fullscreen mode Exit fullscreen mode
  • Just below the register endpoint, enter the following function:

app.post("/login", (request, response) => {

})

Enter fullscreen mode Exit fullscreen mode
  • Let's check if the email the user enter on login exists with the following line of code:

  User.findOne({ email: request.body.email })

Enter fullscreen mode Exit fullscreen mode

Next, we will use a then...catch... block to check if the email search above was successful or not

  • If it is unsuccessful, we will capture that in the catch block like so:

User.findOne({ email: request.body.email })
    .then()
    .catch((e) => {
      response.status(404).send({
        message: "Email not found",
        e,
      });
    });

Enter fullscreen mode Exit fullscreen mode
  • If successful, we will compare the password entered against the hashed password in our database. We are doing this in the then... block like so:

   .then((user)=>{
      bcrypt.compare(request.body.password, user.password)
   })

Enter fullscreen mode Exit fullscreen mode

We will then use a then...catch... block again to check if the comparison is successful or not

  • If the comparison is unsuccessful, we will return an error message in the catch block like so:

    .then((user)=>{
      bcrypt.compare(request.body.password, user.password)
      .then()
      .catch((error) => {
        response.status(400).send({
          message: "Passwords does not match",
          error,
        });
      })
    })

Enter fullscreen mode Exit fullscreen mode
  • Let's double check if the password is correct in the then block

      .then((passwordCheck) => {

          // check if password matches
          if(!passwordCheck) {
            return response.status(400).send({
              message: "Passwords does not match",
              error,
            });
          }
        })

Enter fullscreen mode Exit fullscreen mode
  • If the password matches, then create a random token with the jwt.sign() function. It takes 3 parameters i.e. jwt.sign(payload, secretOrPrivateKey, [options, callback]). You can read more here

bcrypt.compare(request.body.password, user.password)
      .then((passwordCheck) => {

          // check if password matches
          if(!passwordCheck) {
            return response.status(400).send({
              message: "Passwords does not match",
              error,
            });
          }

        //   create JWT token
        const token = jwt.sign(
          {
            userId: user._id,
            userEmail: user.email,
          },
          "RANDOM-TOKEN",
          { expiresIn: "24h" }
        );
      })

Enter fullscreen mode Exit fullscreen mode
  • Finally, return a success message with the token created

.then((user)=>{
      bcrypt.compare(request.body.password, user.password)
      .then((passwordCheck) => {

          // check if password matches
          if(!passwordCheck) {
            return response.status(400).send({
              message: "Passwords does not match",
              error,
            });
          }

        //   create JWT token
        const token = jwt.sign(
          {
            userId: user._id,
            userEmail: user.email,
          },
          "RANDOM-TOKEN",
          { expiresIn: "24h" }
        );

         //   return success response
         response.status(200).send({
          message: "Login Successful",
          email: user.email,
          token,
        });
      })

Enter fullscreen mode Exit fullscreen mode
  • Our Login Endpoint now looks like this:

// login endpoint
app.post("/login", (request, response) => {
  // check if email exists
  User.findOne({ email: request.body.email })

    // if email exists
    .then((user) => {
      // compare the password entered and the hashed password found
      bcrypt
        .compare(request.body.password, user.password)

        // if the passwords match
        .then((passwordCheck) => {

          // check if password matches
          if(!passwordCheck) {
            return response.status(400).send({
              message: "Passwords does not match",
              error,
            });
          }

          //   create JWT token
          const token = jwt.sign(
            {
              userId: user._id,
              userEmail: user.email,
            },
            "RANDOM-TOKEN",
            { expiresIn: "24h" }
          );

          //   return success response
          response.status(200).send({
            message: "Login Successful",
            email: user.email,
            token,
          });
        })
        // catch error if password do not match
        .catch((error) => {
          response.status(400).send({
            message: "Passwords does not match",
            error,
          });
        });
    })
    // catch error if email does not exist
    .catch((e) => {
      response.status(404).send({
        message: "Email not found",
        e,
      });
    });
});


Enter fullscreen mode Exit fullscreen mode

Testing

  • Let's try to login with the credentials we registered in the last tutorial. See the random token generated on a successful login

Login Success Image

  • If email is incorrect or does not exist

Email incorrect or does not exist

  • If password is incorrect

Password incorrect

At this point, you can put hands together for yourself because you have just conquered AUTHENTICATION

👏🏼👏🏼👏🏼👏🏼👏🏼

Conclusion

We began this authentication series by setting up out database in PART 1, we created a model for the user collection and a register endpoint in the PART 2 and finally, in this part, we have successfully created the login endpoint checking if users exist or not.

Congratulations!!! 🍾🍾🍾

We will look into Protecting Endpoints from unauthenticated users next. I hope to catch you there.

Meanwhile, all codes are here

GitHub logo EBEREGIT / auth-backend

This tutorial teaches how to create authentication for a user using nodejs and mongoDB

Top comments (4)

Collapse
 
bralexsvg profile image
Adam Alex

eiii please am not getting you ooo

Collapse
 
ebereplenty profile image
NJOKU SAMSON EBERE

I hope the call made things clearer.

It is important to pay attention to every detail. That is why I make the tutorial step by step. I also make indicators on the screenshots.

Please Follow these indicators

Collapse
 
bralexsvg profile image
Adam Alex

Where was the user data added to the database?
Please make things more clearer

Collapse
 
ebereplenty profile image
NJOKU SAMSON EBERE

I hope the call made things clearer.

It is important to pay attention to every detail. That is why I make the tutorial step by step. I also make indicators on the screenshots.

Please Follow these indicators