Home > database >  How to protect routes using JWT in NextJS?
How to protect routes using JWT in NextJS?

Time:09-19

I was working on a project in next js where i need to protect some routes. I was trying to do this using jwt but for some reason it's not working, the POST method below inside index.js is injecting new entry in db bypass the verify token middleware. Any kind of help would be greatly appreciated.

verifyAuthToken.middleware.js

import jwt from "jsonwebtoken";

export default function verifyAuthToken(req, res) {
  try {
    const token = req.headers;
    if (!token) {
      return res.status(401).json({
        success: false,
        msg: "You are not authorized to access this route",
      });
    }

    const { userId } = jwt.verify(
      req.headers.authorization,
      process.env.TOKEN_SECRET
    );
    if (!userId) {
      return res.status(401).json({
        success: false,
        msg: "You are not authorized to access this route",
      });
    }
    req.userId = userId;
  } catch (error) {
    res.status(401).json({
      success: false,
      msg: "You are not authorized to access this route",
      error: error.message,
    });
  }
}

index.js

import verifyAuthToken from "../../../middleware/verifyAuthToken.middleware";
import Evoluter from "../../../models/Evoluter.model";
import dbConnect from "../../../server-utils/connectDB";
import { sendEmail } from "../../../server-utils/sendEmail";
import baseURL from "../../../utils/baseURL";

export default async (req, res) => {
  const { method } = req;
  verifyAuthToken(req, res);
  await dbConnect();

  switch (method) {
    // @route   GET api/evoluters
    // @desc    Create new evoluter
    // @access  Private
    case "POST":
      try {
        const { name, email } = req.body;

        const evoluter = await Evoluter.findOne({ email: email.toLowerCase() });
        if (evoluter) {
          return res.status(400).json({
            success: false,
            msg: "Evoluter already exists",
          });
        }

        const newEvoluter = await Evoluter.create({
          name,
          email: email.toLowerCase(),
        });

        try {
          await sendEmail({
            email: newEvoluter.email,
            subject: "Welcome to Rubrica",
            message: `Hi ${newEvoluter.name}, welcome to Rubrica. Please click on the link below to activate your account. ${baseURL}/home/${newEvoluter._id}`,
          });

          res.status(201).json({
            success: true,
            data: newEvoluter,
            msg: "Evoluter created successfully. Please check your email to activate your account.",
          });
        } catch (error) {
          console.log(error);
          res.status(500).json({
            success: false,
            msg: "Error sending invitation email, please let the admin know.",
          });
        }
      } catch (error) {
        res.status(400).json({
          success: false,
          msg: "Sorry, we couldn't send the invitation. Please try again.",
          error: error,
        });
      }
      break;

    default:
      res.status(400).json({
        success: false,
        msg: "Invalid request",
      });
      break;
  }
};

Here we can see that the verify token middleware was fired as expected, however the data inside the body got injected into the DB which we don't really need.

Postman output

Please let me know if you need more information I don't have much experience asking questions in stackoverflow.

CodePudding user response:

It is bypassing the verifyAuthToken function because You are doing it anyway you are just generating response on verifyAuthToken

You can return a boolean at the end of your verifyAuthToken something like this:

if (userId) return true; 
else return false;

Then in your index.js before injecting data to database instead of verifyAuthToken(req, res); do this:

if (!verifyAuthToken(req, res)) {
    return;
}

You can also use NextJs middleware

  • Related