Authentication is one of the most important parts of any web application. Without it, your users can’t securely log in, access their data, or trust your app. In this guide, we’ll learn how to implement authentication in Express.js using Mongoose with JWT (JSON Web Tokens).
By the end, you’ll have a working setup with Register, Login, and Protected Routes.
Step 1: Setup the Project
Initialize a new project:
mkdir express-auth && cd express-auth
npm init -y
Install dependencies:
npm install express mongoose bcrypt jsonwebtoken dotenv cors
npm install --save-dev nodemon
Project structure:
📂 express-auth
┣ 📂 models
┃ ┗ user.model.js
┣ 📂 routes
┃ ┗ auth.routes.js
┣ 📂 middlewares
┃ ┗ auth.middleware.js
┣ server.js
┣ .env
Step 2: Connect to MongoDB
Inside server.js
import express from "express";
import mongoose from "mongoose";
import dotenv from "dotenv";
import cors from "cors";
dotenv.config();
const app = express();
app.use(express.json());
app.use(cors());
mongoose
.connect(process.env.MONGO_URI)
.then(() => console.log("MongoDB connected"))
.catch((err) => console.error(err));
app.listen(5000, () => console.log("Server running on port 5000"));
Step 3: Create User Model
models/user.model.js
import mongoose from "mongoose";
import bcrypt from "bcrypt";
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
// Hash password before saving
userSchema.pre("save", async function (next) {
if (!this.isModified("password")) return next();
this.password = await bcrypt.hash(this.password, 10);
next();
});
const User = mongoose.model("User", userSchema);
export default User;
Auth Routes (Register & Login)
*routes/auth.routes.js
*
import express from "express";
import jwt from "jsonwebtoken";
import bcrypt from "bcrypt";
import User from "../models/user.model.js";
const router = express.Router();
// Register
router.post("/register", async (req, res) => {
try {
const { name, email, password } = req.body;
const existing = await User.findOne({ email });
if (existing) return res.status(400).json({ message: "User already exists" });
const user = new User({ name, email, password });
await user.save();
res.status(201).json({ message: "User registered successfully" });
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// Login
router.post("/login", async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(400).json({ message: "Invalid credentials" });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ message: "Invalid credentials" });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: "1h" });
res.json({ token, user: { id: user._id, name: user.name, email: user.email } });
} catch (err) {
res.status(500).json({ message: err.message });
}
});
export default router;
🛠️ Step 5: Middleware for Protecting Routes
middlewares/auth.middleware.js
import jwt from "jsonwebtoken";
export const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(" ")[1]; // Bearer <token>
if (!token) return res.status(401).json({ message: "No token provided" });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch {
res.status(401).json({ message: "Invalid token" });
}
};
✅ Best Practices
🔒 Never store plain-text passwords. Always hash them.
⏳ Use short-lived JWTs + refresh tokens for long sessions.
🔑 Keep your JWT_SECRET safe and outside source code.
🍪 Prefer HttpOnly cookies for storing tokens in production.
🌐 Always use HTTPS in production.
🎯 Conclusion
You just built authentication in Express with Mongoose and JWT!
We created a User model, added Register/Login routes, generated JWT tokens, and protected routes with a middleware.
👉 Next steps:
Add role-based authorization (admin, user, etc.)
Implement refresh tokens for longer sessions
Add OAuth (Google/GitHub login)
🔥 That’s it! You now have a secure authentication system in your Express app.
Top comments (0)