Authentication with Nodejs and mongoDB - Part 4
Tags: tutorial, mongodb, node, express
Published: 2020-10-11 16:08:31

This will be the final part of this authentication series with Nodejs and mongoDB. Please checkout the [previous article](https://dev.to/ebereplenty/authentication-with-nodejs-and-mongodb-part-3-3mic) to catch up quickly.

In this tutorial, we will be looking at protecting some routes until a user is authenticated (logged in). Stick with me.

## Starter project
The starter project for this tutorial can be gotten [here](https://github.com/EBEREGIT/auth-backend/tree/login-endpoint)

* Open your terminal and run ``git clone --branch login-endpoint https://github.com/EBEREGIT/auth-backend``. 
* Navigate into the folder ``cd auth-backend``.
* Run ``npm install``.
* Run ``nodemon index``. This starts up the server

## Create 2 endpoints
We will need 2 endpoints in order to be able to show how authorization works. Copy the following endpoints and paste into the ``app.js`` file just before the last line.

```javascript
// free endpoint
app.get("/free-endpoint", (request, response) => {
  response.json({ message: "You are free to access me anytime" });
});

// authentication endpoint
app.get("/auth-endpoint", (request, response) => {
  response.json({ message: "You are authorized to access me" });
});
```

*Feel free to check if the endpoints are working on postman or a browser*

## Create the authentication function
Here, we are creating a function that will enable us protect a particular endpoint until the user is authenticated.

* Create a file in the root directory and name it ``auth.js``

* Import ``jasonwebtoken`` at the top of the file

```javascript

const jwt = require("jsonwebtoken");

```

* Create and export an asynchronous function in which our authorization code will live

```javascript

module.exports = async (request, response, next) => {
    
}

```

* In the function, we will use a ``try...catch...`` block to check if a user is logged in.

```javascript

    try {
        
    } catch (error) {
        response.status(401).json({
            error: new Error("Invalid request!"),
          });
    }

```

* In the ``try{}`` block, let's get the authentication token from the ``authorization header``

```javascript

//   get the token from the authorization header
    const token = await request.headers.authorization.split(" ")[1];

```

* Next, let's check if the token that was generated matches the token string (**RANDOM-TOKEN**) we entered initially

```javascript

//check if the token matches the supposed origin
    const decodedToken = await jwt.verify(
      token,
      "RANDOM-TOKEN"
    );

```

* Next, pass in the details of the ``decodedToken`` to ``user`` constant

```javascript

// retrieve the user details of the logged in user
    const user = await decodedToken;

```

* Pass the ``user`` to the endpoint like so:

```javascript

// pass the the user down to the endpoints here
    request.user = user;

```

Finally, open the way to the endpoint like so:

```javascript

// pass down functionality to the endpoint
    next();

```

> Our ``auth.js`` file now looks like this:


```javascript

const jwt = require("jsonwebtoken");

module.exports = async (request, response, next) => {
  try {
    //   get the token from the authorization header
    const token = await request.headers.authorization.split(" ")[1];

    //check if the token matches the supposed origin
    const decodedToken = await jwt.verify(token, "RANDOM-TOKEN");

    // retrieve the user details of the logged in user
    const user = await decodedToken;

    // pass the the user down to the endpoints here
    request.user = user;

    // pass down functionality to the endpoint
    next();
    
  } catch (error) {
    response.status(401).json({
      error: new Error("Invalid request!"),
    });
  }
};

```

## Protecting the endpoint
This is the final and simplest step. We will start by importing the authentication function to the ``app.js`` file like so:

```javascript

const auth = require("./auth");

```

Now go to the authentication endpoint in the ``app.js`` file and add ``auth`` as a second argument like so

```javascript

// authentication endpoint
app.get("/auth-endpoint", auth, (request, response) => {
  response.json({ message: "You are authorized to access me" });
});

```

And that is it. That is all we need to protect that route. Let's test it out

## Testing
> If the user is not logged in

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k9tlcam9ef4hjh93qeha.JPG)

> If the user is logged in

* Login Like so:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/has8qii5z8srvlu5nbp9.JPG)

* Copy the token

* Open a new tab on ``postman``

* Select ``bearer token`` in the authentication type

* Paste the token in the ``token`` field and send the request

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s7evrpmfjy3mmfi5vtlb.JPG)

## CORS
One last thing!

We need to handle CORS error. This will allow the user in the frontend to consume the APIs that we have created without any problem.

* To do this navigate to the ``app.js`` file

* Add the following code just below the ``dbConnect()`` line

```javascript

// Curb Cores Error by adding a header here
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content, Accept, Content-Type, Authorization"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PUT, DELETE, PATCH, OPTIONS"
  );
  next();
});

```

And with this, you are a nodejs authentication champion!!!

### Conclusion
This part concludes this series on authentication with nodejs and mongoDB. We have seen how to create a registration and login endpoint, how to create protection on the endpoints if we deem fit.

All codes are found [here](https://github.com/EBEREGIT/auth-backend/tree/auth-middleware)

Next, we will be looking at [how to host this app on heroku](https://dev.to/ebereplenty/hosting-a-nodejs-and-mongodb-app-on-heroku-38b8). See you soon