DEV Community

loading...

Authentication with Nodejs and mongoDB - Part 4

ebereplenty profile image NJOKU SAMSON EBERE Updated on ・4 min read

This will be the final part of this authentication series with Nodejs and mongoDB. Please checkout the previous article 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

  • 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.

// 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" });
});
Enter fullscreen mode Exit fullscreen mode

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


const jwt = require("jsonwebtoken");

Enter fullscreen mode Exit fullscreen mode
  • Create and export an asynchronous function in which our authorization code will live

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

}

Enter fullscreen mode Exit fullscreen mode
  • In the function, we will use a try...catch... block to check if a user is logged in.

    try {

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

Enter fullscreen mode Exit fullscreen mode
  • In the try{} block, let's get the authentication token from the authorization header

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

Enter fullscreen mode Exit fullscreen mode
  • Next, let's check if the token that was generated matches the token string (RANDOM-TOKEN) we entered initially

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

Enter fullscreen mode Exit fullscreen mode
  • Next, pass in the details of the decodedToken to user constant

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

Enter fullscreen mode Exit fullscreen mode
  • Pass the user to the endpoint like so:

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

Enter fullscreen mode Exit fullscreen mode

Finally, open the way to the endpoint like so:


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

Enter fullscreen mode Exit fullscreen mode

Our auth.js file now looks like this:


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

Enter fullscreen mode Exit fullscreen mode

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:


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

Enter fullscreen mode Exit fullscreen mode

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


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

Enter fullscreen mode Exit fullscreen mode

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

If the user is logged in

  • Login Like so:

Alt Text

  • 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

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


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

Enter fullscreen mode Exit fullscreen mode

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

Next, we will be looking at how to host this app on heroku. See you soon

Discussion (2)

pic
Editor guide
Collapse
gmcamposano profile image
gmcamposano

Excellent Njoku! Thank you man

Collapse
ebereplenty profile image
NJOKU SAMSON EBERE Author

You are welcome.
I am happy you found it helpful