Authentication with Nodejs and mongoDB - Part 3
Tags: tutorial, mongodb, database, node
Published: 2020-09-27 06:57:37

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](https://dev.to/ebereplenty/authentication-with-nodejs-and-mongodb-part-1-10pn) and [part 2](https://dev.to/ebereplenty/authentication-with-nodejs-and-mongodb-part-2-1hg9).

In this part of the tutorial, we will be covering the login with [``jasonwebtoken (JWT)``](https://www.npmjs.com/package/jsonwebtoken). 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](https://github.com/EBEREGIT/auth-backend/tree/register-endpoint)

## Login Endpoint
* Install JWT

```javascript

npm i jsonwebtoken -s

```

* Import ``JWT`` just below the ``const bcrypt = require("bcrypt");`` line at the top of the ``app.js`` file like so:

```javascript

const jwt = require("jsonwebtoken");

```

* Just below the ``register`` endpoint, enter the following function:

```javascript

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

```
* Let's check if the email the user enter on login exists with the following line of code:

```javascript

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

```

*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:

```javascript

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

```

* 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:

```javascript

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

```

*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:

```javascript

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

```

* Let's double check if the password is correct in the ``then`` block

```javascript

      .then((passwordCheck) => {

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

```

* 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](https://www.npmjs.com/package/jsonwebtoken#usage)

```javascript

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" }
        );
      })

```

* Finally, return a success message with the token created

```javascript

.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,
        });
      })

```
* Our Login Endpoint now looks like this:

```javascript

// 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,
      });
    });
});


```

## 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](https://dev-to-uploads.s3.amazonaws.com/i/krz1ikslqsilk1d8lvpr.JPG)

* If ``email`` is incorrect or does not exist

![Email incorrect or does not exist](https://dev-to-uploads.s3.amazonaws.com/i/xy9ka8we8n2nvdaeain4.JPG)

* If ``password`` is incorrect

![Password incorrect](https://dev-to-uploads.s3.amazonaws.com/i/tvq3cvsoh3ff24zl9e5k.JPG)

**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](https://dev.to/ebereplenty/authentication-with-nodejs-and-mongodb-part-4-4p37) next. I hope to catch you there. 

Meanwhile, all codes are [here](https://github.com/EBEREGIT/auth-backend/tree/login-endpoint)

{% github eberegit/auth-backend no-readme %}