DEV Community

Cover image for Implementing Authentication Using JWT and Passport.js: A Beginner’s Guide
Hardik Gayner
Hardik Gayner

Posted on

Implementing Authentication Using JWT and Passport.js: A Beginner’s Guide

Introduction

Authentication is a crucial part of web applications, ensuring that only authorized users can access certain resources. One of the most secure and scalable authentication methods is JWT (JSON Web Token) authentication. In this guide, we will implement JWT authentication using Passport.js, a popular authentication middleware for Node.js.

What is JWT?

JSON Web Token (JWT) is a compact, URL-safe token format used for securely transmitting information between parties as a JSON object. It consists of three parts:

  1. Header – Contains metadata about the token (e.g., algorithm used).
  2. Payload – Contains user-related data (e.g., user ID).
  3. Signature – Ensures the token's integrity and authenticity.

Why Use Passport.js?

Passport.js is a middleware that simplifies authentication in Node.js applications. It supports various strategies, including JWT authentication.

Project Setup

Step 1: Initialize a Node.js Project

mkdir jwt-auth-example
cd jwt-auth-example
npm init -y
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Required Dependencies

npm install express passport passport-jwt jsonwebtoken dotenv bcryptjs mongoose
Enter fullscreen mode Exit fullscreen mode
  • express – Web framework for Node.js
  • passport – Authentication middleware
  • passport-jwt – JWT strategy for Passport.js
  • jsonwebtoken – Library for generating JWTs
  • dotenv – Loads environment variables
  • bcryptjs – Hashes passwords securely
  • mongoose – MongoDB ORM

Building the Authentication System

Step 3: Create the Folder Structure

jwt-auth-example
│── config/
│   ├── passport.js
│── models/
│   ├── User.js
│── routes/
│   ├── auth.js
│── server.js
│── .env
│── package.json
Enter fullscreen mode Exit fullscreen mode

Step 4: Setup MongoDB and User Model

Connect to MongoDB

Create a .env file and add your MongoDB connection string:

MONGO_URI=mongodb://localhost:27017/jwt-auth
JWT_SECRET=your_secret_key
Enter fullscreen mode Exit fullscreen mode

Create User.js Model (inside models/ folder)

const mongoose = require("mongoose");

const UserSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
});

module.exports = mongoose.model("User", UserSchema);
Enter fullscreen mode Exit fullscreen mode

Step 5: Configure Passport.js for JWT Authentication

Create passport.js (inside config/ folder)

const JwtStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require("passport-jwt").ExtractJwt;
const User = require("../models/User");
const dotenv = require("dotenv");

dotenv.config();

const opts = {
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: process.env.JWT_SECRET,
};

module.exports = (passport) => {
  passport.use(
    new JwtStrategy(opts, async (jwt_payload, done) => {
      try {
        const user = await User.findById(jwt_payload.id);
        if (user) {
          return done(null, user);
        }
        return done(null, false);
      } catch (err) {
        console.error(err);
      }
    })
  );
};
Enter fullscreen mode Exit fullscreen mode

Step 6: Create Authentication Routes

Create auth.js (inside routes/ folder)

const express = require("express");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const passport = require("passport");
const User = require("../models/User");
const dotenv = require("dotenv");

dotenv.config();
const router = express.Router();

// Register Route
router.post("/register", async (req, res) => {
  const { username, email, password } = req.body;

  try {
    let user = await User.findOne({ email });
    if (user) return res.status(400).json({ msg: "User already exists" });

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

    user = new User({ username, email, password: hashedPassword });
    await user.save();
    res.json({ msg: "User registered successfully" });
  } catch (err) {
    res.status(500).json({ msg: "Server error" });
  }
});

// Login Route
router.post("/login", async (req, res) => {
  const { email, password } = req.body;

  try {
    const user = await User.findOne({ email });
    if (!user) return res.status(400).json({ msg: "User not found" });

    const isMatch = await bcrypt.compare(password, user.password);
    if (!isMatch) return res.status(400).json({ msg: "Invalid credentials" });

    const payload = { id: user.id, username: user.username };

    jwt.sign(
      payload,
      process.env.JWT_SECRET,
      { expiresIn: "1h" },
      (err, token) => {
        if (err) throw err;
        res.json({ token });
      }
    );
  } catch (err) {
    res.status(500).json({ msg: "Server error" });
  }
});

// Protected Route
router.get(
  "/profile",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    res.json({ user: req.user });
  }
);

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Step 7: Set Up the Server

Create server.js

const express = require("express");
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const passport = require("passport");
const authRoutes = require("./routes/auth");

dotenv.config();
const app = express();

app.use(express.json());

mongoose
  .connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log("MongoDB connected"))
  .catch((err) => console.error(err));

require("./config/passport")(passport);
app.use(passport.initialize());

app.use("/api/auth", authRoutes);

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Enter fullscreen mode Exit fullscreen mode

Testing the Authentication System

  1. Start the Server
   node server.js
Enter fullscreen mode Exit fullscreen mode
  1. Register a User
   curl -X POST http://localhost:5000/api/auth/register -H "Content-Type: application/json" -d '{"username": "hardik", "email": "hardik@example.com", "password": "123456"}'
Enter fullscreen mode Exit fullscreen mode
  1. Login to Get a Token
   curl -X POST http://localhost:5000/api/auth/login -H "Content-Type: application/json" -d '{"email": "hardik@example.com", "password": "123456"}'
Enter fullscreen mode Exit fullscreen mode
  • Copy the received JWT token.
    1. Access the Protected Route
   curl -X GET http://localhost:5000/api/auth/profile -H "Authorization: Bearer YOUR_JWT_TOKEN"
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this guide, we implemented JWT authentication using Passport.js in a Node.js application. We covered:

✅ User registration & password hashing

✅ User login with JWT generation

✅ Protecting routes using Passport.js

This approach ensures secure authentication in modern web applications. 🚀

Top comments (0)