All posts
·12 min·MERN

Complete JWT Authentication in MERN Stack

Learn how to implement complete JWT authentication in a MERN stack application, including backend and frontend integration.

Complete JWT Authentication in MERN Stack

Why JWT Authentication?

JWTs provide stateless authentication that scales well across distributed systems. Each token contains:

  • Header (algorithm and token type)
  • Payload (user data and claims)
  • Signature (verification)

Backend Implementation

1. Configure Auth Routes


  // routes/authRoutes.js
  const express = require('express');
  const { register, login, refresh, logout } = require('../controllers/authController');
  const router = express.Router();
  
  router.post('/register', register);
  router.post('/login', login);
  router.post('/refresh', refresh);
  router.post('/logout', logout);

2. Create Auth Controller


  // controllers/authController.js
  const jwt = require('jsonwebtoken');
  const bcrypt = require('bcryptjs');
  const User = require('../models/User');
  const Token = require('../models/Token');
  
  const generateAccessToken = (userId) => {
    return jwt.sign({ userId }, process.env.ACCESS_TOKEN_SECRET, {
      expiresIn: '15m'
    });
  };
  
  const generateRefreshToken = (userId) => {
    return jwt.sign({ userId }, process.env.REFRESH_TOKEN_SECRET, {
      expiresIn: '7d'
    });
  };
  
  exports.register = async (req, res) => {
    try {
      const { email, password } = req.body;
      const hashedPassword = await bcrypt.hash(password, 12);
      const user = await User.create({ email, password: hashedPassword });
      
      const accessToken = generateAccessToken(user._id);
      const refreshToken = generateRefreshToken(user._id);
      
      await new Token({ userId: user._id, token: refreshToken }).save();
      
      res.cookie('refreshToken', refreshToken, {
        httpOnly: true,
        maxAge: 7 * 24 * 60 * 60 * 1000,
        secure: process.env.NODE_ENV === 'production'
      });
      
      res.status(201).json({ accessToken });
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  };

Frontend Implementation

1. Create Auth Context


  // context/AuthContext.jsx
  import { createContext, useContext, useEffect, useState } from 'react';
  import axios from 'axios';
  
  const AuthContext = createContext();
  
  export const AuthProvider = ({ children }) => {
    const [user, setUser] = useState(null);
    const [accessToken, setAccessToken] = useState('');
  
    const login = async (credentials) => {
      const { data } = await axios.post('/api/auth/login', credentials);
      setAccessToken(data.accessToken);
      setUser(data.user);
    };
  
    const refreshAccessToken = async () => {
      try {
        const { data } = await axios.post('/api/auth/refresh', {}, {
          withCredentials: true
        });
        setAccessToken(data.accessToken);
      } catch (error) {
        logout();
      }
    };
  
    useEffect(() => {
      const interval = setInterval(() => {
        refreshAccessToken();
      }, 14 * 60 * 1000); // Refresh before expiration
      
      return () => clearInterval(interval);
    }, []);
  
    return (
      
        {children}
      
    );
  };

Looking for an Individual Expert?

Get the same quality as an agency with the direct accountability of the best freelance developer in Lalitpur.

Saroj Dangol

Saroj Dangol

Senior Full Stack Developer

React · Node.js · Next.js · React Native · AWS

About Saroj →