Logo

dev-resources.site

for different kinds of informations.

Implementing Secure Authentication in Next.js with JWT and MongoDB. Protect Routes using middleware

Published at
7/5/2024
Categories
nextjs
middleware
authjs
security
Author
abdur_rakibrony_97cea0e9
Categories
4 categories in total
nextjs
open
middleware
open
authjs
open
security
open
Author
24 person written this
abdur_rakibrony_97cea0e9
open
Implementing Secure Authentication in Next.js with JWT and MongoDB. Protect Routes using middleware

In modern web development, implementing a robust authentication system is crucial for securing user data and providing a seamless user experience. In this blog post, we'll explore how to implement authentication in a Next.js application using JSON Web Tokens (JWT) and MongoDB. We'll cover the key aspects of this implementation, including middleware, token management, and user registration and login.

Setting Up Middleware for Route Protection
The middleware function plays a crucial role in protecting routes and ensuring that users are authenticated before accessing certain pages. Here's the implementation of the middleware function:

import { getToken, verifyToken } from "@/lib/auth";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export async function middleware(request: NextRequest) {
  const token = getToken(request);
  const { pathname } = request.nextUrl;

  if (token) {
    const payload = await verifyToken(token);
    if (payload) {
      if (pathname === "/" || pathname === "/register") {
        return NextResponse.redirect(new URL("/home", request.url));
      }
      return NextResponse.next();
    }
  }

  if (pathname !== "/" && pathname !== "/register") {
    return NextResponse.redirect(new URL("/", request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};

Enter fullscreen mode Exit fullscreen mode

This middleware function checks if a token exists and verifies it. If the token is valid, it allows the user to proceed to the requested route. If the token is invalid or missing, it redirects the user to the login page.

Managing Tokens with JSON Web Tokens (JWT)
To handle token generation and verification, we use the jose library. Below are the utility functions for managing JWTs:

import { jwtVerify, SignJWT } from 'jose';
import { NextRequest } from "next/server";

export function getToken(req: NextRequest) {
  return req.cookies.get("token")?.value;
}

export async function verifyToken(token: string) {
  if (!token) return null;

  try {
    const secret = new TextEncoder().encode(process.env.JWT_SECRET);
    const { payload } = await jwtVerify(token, secret);
    return payload as { userId: string };
  } catch (error) {
    console.error('Token verification failed:', error);
    return null;
  }
}

export async function createToken(payload: { userId: string }) {
  const secret = new TextEncoder().encode(process.env.JWT_SECRET!);
  const token = await new SignJWT(payload)
    .setProtectedHeader({ alg: 'HS256' })
    .setExpirationTime('1d')
    .sign(secret);
  return token;
}

Enter fullscreen mode Exit fullscreen mode

These functions handle retrieving the token from cookies, verifying the token, and creating a new token. The verifyToken function ensures that the token is valid and extracts the payload, while createToken generates a new token with a specified payload.

User Registration and Login
For user registration and login, we need to handle form data, hash passwords, and create tokens. Here's how we achieve this:

"use server";
import { cookies } from "next/headers";
import bcrypt from "bcryptjs";
import { connectToDB } from "@/lib/db";
import User from "@/models/User";
import { loginSchema, registerSchema } from "@/zod/schema";
import { createToken } from "@/lib/auth";

export async function registerUser(formData: FormData) {
  await connectToDB();

  const parsedData = registerSchema.parse(
    Object.fromEntries(formData.entries())
  );

  const existingUser = await User.findOne({ email: parsedData.email });
  if (existingUser) {
    throw new Error("Email already exists");
  }

  const hashedPassword = await bcrypt.hash(parsedData.password, 10);

  const newUser = await User.create({
    ...parsedData,
    password: hashedPassword,
    createdAt: new Date(),
  });

  const token = await createToken({ userId: newUser._id.toString() });

  const cookieStore = cookies();
  cookieStore.set("token", token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
  });
}

export async function loginUser(formData: FormData) {
  const { email, password } = loginSchema.parse(
    Object.fromEntries(formData.entries())
  );

  await connectToDB();

  const user = await User.findOne({ email });
  if (!user) {
    throw new Error("Invalid credentials");
  }

  const isPasswordValid = await bcrypt.compare(password, user.password);
  if (!isPasswordValid) {
    throw new Error("Invalid credentials");
  }

  const token = await createToken({ userId: user._id.toString() });

  const cookieStore = cookies();
  cookieStore.set("token", token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
  });
}

export async function logoutUser() {
  cookies().set("token", "", { expires: new Date(0) });
}

Enter fullscreen mode Exit fullscreen mode

registerUser: This function handles user registration. It connects to the database, parses the form data, checks if the email already exists, hashes the password, creates a new user, generates a token, and sets the token as an HTTP-only cookie.

loginUser: This function handles user login. It parses the form data, connects to the database, verifies the user's credentials, generates a token, and sets the token as an HTTP-only cookie.

logoutUser: This function handles user logout by clearing the token cookie.

Conclusion
Implementing authentication in a Next.js application using JWT and MongoDB provides a secure and efficient way to manage user sessions. By leveraging middleware, JWT, and MongoDB, we can protect routes, verify tokens, and handle user registration and login seamlessly.

authjs Article's
30 articles in total
Favicon
Authentication System Using NodeJS
Favicon
Add Authjs to Next.js 15 app router with GitHub Authentication
Favicon
Master Authentication with Auth.js, Next.js, and PostgreSQL: A Comprehensive Guide
Favicon
Nuxt Authorization: How to Implement Team Role-Based Access Control in Nuxt 3
Favicon
Mastering Authentication in Next.js: A Step-by-Step Guide to GitHub Login with Auth.js
Favicon
User Authentication with Auth.js in Next.js App Router
Favicon
Lucia Auth is getting deprected
Favicon
Integrating GitHub Authentication with NextAuth.js: A Step-by-Step Guide
Favicon
Simple Next.js Magic Link JWT Authentication with Prisma, PostgreSQL, and Resend
Favicon
Password Authentication with Auth.js in Astro and Customizing Session Information (auth-astro)
Favicon
Basic Authentication for Nuxt.js (JSON Web Token + Local Storage)
Favicon
Implementing Federated Sign-Out with Auth.js in Next.js 14 App Router
Favicon
Integrating LinkedIn Authentication with NextAuth.js: A Step-by-Step Guide
Favicon
Implementing auth.js v5 with Prisma and Supabase in Next.js
Favicon
Auth, OAuth, and Auth0: What is what?
Favicon
JWT Authentication and Cookie Management in Web Applications
Favicon
๐Ÿš€ Exciting News!
Favicon
Data Persistence (Cookies, Sessions, Tokens, LocalStorage and SessionStorage)
Favicon
Fashion website
Favicon
The Firebase Shortcut: Simplifying Next.js Authentication
Favicon
Authentication system in Next.Js using Auth.js
Favicon
Roles based authentication using Nextauth and next.js
Favicon
Authentication & Authorization
Favicon
Top User Authentication Tools for Developers
Favicon
Comprehensive Guide to SvelteKitAuth: Secure Authentication for SvelteKit Apps
Favicon
Building a Secure OTP-based Login System in Next.js
Favicon
Implementing Secure Authentication in Next.js with JWT and MongoDB. Protect Routes using middleware
Favicon
Next.js 14 and NextAuth v4 : Credentials Authentication A Detailed Step-by-Step Guide
Favicon
Building a Secure OTP-based Login System in Next.js
Favicon
Web3Auth(ๆฌกใฎjs)ใ‚’ไฝฟ็”จใ—ใŸXRP Ledgerใ‚ขใ‚ซใ‚ฆใƒณใƒˆใฎไฝœๆˆ:ใ‚นใƒ†ใƒƒใƒ—ใƒใ‚คใ‚นใƒ†ใƒƒใƒ—ใ‚ฌใ‚คใƒ‰

Featured ones: