Crafting a Secure Authentication System with JWT and middleware

Aneeqa Khan - Nov 18 '23 - - Dev Community

Table of Contents

For this series, I'm following an excellent video tutorial from Traversy Media

Introduction

In this blog, we'll dive into the development of a robust authentication system for your application. We'll start by creating a protect middleware that ensures the safety of our users' data.

Create protect middleware

Firstly, we'll start with creating an authMiddleware.js file in the middleware folder.



const jwt = require("jsonwebtoken");
const asyncHandler = require("express-async-handler");
const User = require("../models/userModel");

const protect = asyncHandler(async (req, res, next) => {
  let token;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith("Bearer")
  ) {
    try {
      // get token from header
      token = req.headers.authorization.split(" ")[1];

      // verify token
      const decoded = jwt.verify(token, process.env.JWT_SECRET);

      // get user from the token
      req.user = await User.findById(decoded.id).select("-password");

      next();
    } catch (error) {
      console.log(error);
      res.status(401);
      throw new Error("Not Authorized");
    }
  }
  if (!token) {
    res.status(401);
    throw new Error("Not Authorized, no token");
  }
});

module.exports = { protect };


Enter fullscreen mode Exit fullscreen mode

In this function, we retrieve the token from the request headers and verify it to determine if the decoded token's id matches any user in the database. If it doesn't find a user or if the token is missing, in such cases, we throw an error.

Get current user data

Next, we'll create a function to get the currently logged-in user data in userController.js.



const getLoggedInUser = asyncHandler(async (req, res) => {
  const { _id, name, email } = await User.findById(req.user.id);
  res.status(200).json({
    id: _id,
    name,
    email,
  });
});


Enter fullscreen mode Exit fullscreen mode

Protect the user data route

In the last, We'll use protect middleware to secure the user data route. Add these lines to the userRoutes.js file.



// import middleware
const { protect } = require("../middleware/authMiddleware");

...
// Add a protect as a second param
router.get("/me", protect, getLoggedInUser); 
...


Enter fullscreen mode Exit fullscreen mode

Now, let's check this functionality with no token

no jwt token

Now add the correct token

secure user data

And now test it with an invalid token

invalid token

That's it for today. In the next article, we'll work on protecting the todos routes.

Connect with me

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .