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:
- Header – Contains metadata about the token (e.g., algorithm used).
- Payload – Contains user-related data (e.g., user ID).
- 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
Step 2: Install Required Dependencies
npm install express passport passport-jwt jsonwebtoken dotenv bcryptjs mongoose
-
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
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
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);
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);
}
})
);
};
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;
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}`));
Testing the Authentication System
- Start the Server
node server.js
- 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"}'
- 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"}'
- Copy the received JWT token.
- Access the Protected Route
curl -X GET http://localhost:5000/api/auth/profile -H "Authorization: Bearer YOUR_JWT_TOKEN"
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)