logo
Authentication with JWT in MERN Stack (Step-by-Step)
Kashan Iqbal

Kashan Iqbal

Posted 6 days ago

Authentication with JWT in MERN (Step-by-Step Guide)

Authentication is a must-have for nearly every web application. In the MERN stack (MongoDB, Express, React, Node), JWT (JSON Web Tokens) is the go-to method for handling stateless, secure login systems.

In this guide, you'll learn how to implement user authentication with JWT in a MERN stack app β€” step-by-step.


πŸ” What is JWT?

JWT (JSON Web Token) is a compact, URL-safe token format used to securely transmit information between parties.

It has three parts:

  • Header
  • Payload
  • Signature

Example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

🧱 Folder Structure for Authentication

Assume you're using a clean MERN structure like:

mern-auth/
β”œβ”€β”€ client/        # React
└── server/        # Node + Express
    β”œβ”€β”€ controllers/
    β”œβ”€β”€ models/
    β”œβ”€β”€ routes/
    └── middleware/

πŸ›  Backend Setup (Express + JWT)

1. Install dependencies

npm install express mongoose bcryptjs jsonwebtoken dotenv cors

2. Create User Model (models/User.js)

const mongoose = require("mongoose"); const UserSchema = new mongoose.Schema({ name: String, email: { type: String, unique: true }, password: String, }); module.exports = mongoose.model("User", UserSchema);

3. Create Auth Controller (controllers/auth.js)

const jwt = require("jsonwebtoken"); const bcrypt = require("bcryptjs"); const User = require("../models/User"); exports.register = async (req, res) => { const { name, email, password } = req.body; const hashed = await bcrypt.hash(password, 10); const user = await User.create({ name, email, password: hashed }); res.json(user); }; exports.login = async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) return res.status(400).json({ error: "Invalid credentials" }); const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: "1h" }); res.json({ token }); };

4. JWT Middleware (middleware/auth.js)

const jwt = require("jsonwebtoken"); module.exports = (req, res, next) => { const token = req.headers["authorization"]; if (!token) return res.status(403).send("Access Denied"); try { const verified = jwt.verify(token.split(" ")[1], process.env.JWT_SECRET); req.user = verified; next(); } catch (err) { res.status(400).send("Invalid Token"); } };

5. Auth Routes (routes/auth.js)

const express = require("express"); const { register, login } = require("../controllers/auth"); const router = express.Router(); router.post("/register", register); router.post("/login", login); module.exports = router;

βš›οΈ Frontend (React)

  • Use axios to send login/register requests
  • Store JWT in localStorage or HTTP-only cookies
  • Protect routes using conditional rendering or useEffect
axios.post("/api/login", { email, password }) .then(res => localStorage.setItem("token", res.data.token));

πŸ–ΌοΈ Suggested Image Prompt:

raw

βœ… Final Notes

  • Always hash passwords using bcrypt
  • Don’t store JWTs in localStorage for sensitive apps (use HTTP-only cookies)
  • Set token expiry and refresh logic for long sessions

πŸ” Summary

JWT is lightweight, secure, and scalable β€” perfect for MERN apps.

With this setup, your app is ready for user login, protected APIs, and secure sessions in 2025 and beyond.


Published on: 2025-06-18

Related Articles

No related blogs found.