A "Forgot Password" feature is essential for any user authentication system. It enhances user experience and security by allowing users to reset their passwords safely. In this guide, we’ll walk through implementing this feature using MongoDB, Node.js, Express, and JWT (JSON Web Token).
Prerequisites
Before we begin, ensure you have:
- Node.js & npm installed
- MongoDB set up (local or cloud-based like MongoDB Atlas)
- Basic knowledge of Express & JWT
Step 1: Set Up Your Project
Initialize a new Node.js project:
mkdir forgot-password && cd forgot-password
npm init -y
Install required dependencies:
npm install express mongoose dotenv jsonwebtoken bcryptjs nodemailer cors body-parser
Step 2: Configure MongoDB & Express
Create an .env file to store database credentials:
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret
EMAIL_USER=your_email@example.com
EMAIL_PASS=your_email_password
Set up Express and MongoDB connection in server.js:
const express = require("express");
const mongoose = require("mongoose");
require("dotenv").config();
const app = express();
app.use(express.json());
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 the User Model
Define a User schema in models/User.js:
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
resetToken: { type: String, default: null },
resetTokenExpiry: { type: Date, default: null }
});
module.exports = mongoose.model("User", UserSchema);
Step 4: Implement the Password Reset Flow
1️⃣ Generate Reset Token
Create an endpoint in routes/auth.js to send a reset email:
const express = require("express");
const User = require("../models/User");
const jwt = require("jsonwebtoken");
const nodemailer = require("nodemailer");
const router = express.Router();
router.post("/forgot-password", async (req, res) => {
const { email } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ message: "User not found" });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: "1h" });
user.resetToken = token;
user.resetTokenExpiry = Date.now() + 3600000; // 1 hour
await user.save();
// Email setup
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS
}
});
const mailOptions = {
to: user.email,
subject: "Password Reset",
text: `Click the link to reset your password: http://localhost:3000/reset-password/${token}`
};
await transporter.sendMail(mailOptions);
res.json({ message: "Reset link sent to email" });
});
module.exports = router;
2️⃣ Reset Password
Create an endpoint to reset the password:
router.post("/reset-password", async (req, res) => {
const { token, newPassword } = req.body;
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findOne({ _id: decoded.id, resetToken: token });
if (!user || user.resetTokenExpiry < Date.now()) {
return res.status(400).json({ message: "Invalid or expired token" });
}
user.password = require("bcryptjs").hashSync(newPassword, 10);
user.resetToken = null;
user.resetTokenExpiry = null;
await user.save();
res.json({ message: "Password reset successful" });
} catch (err) {
res.status(400).json({ message: "Invalid token" });
}
});
module.exports = router;
Step 5: Test the Implementation
Send a POST request to /forgot-password
with { "email": "user@example.com" }
.
Check your email for the reset link.
Send a POST request to /reset-password
with { "token": "received_token", "newPassword": "new_secure_password" }
.
Conclusion
You’ve successfully implemented a secure password reset feature with MongoDB, Node.js, and Express. This approach ensures security by validating tokens, hashing passwords, and setting expiration times.
🚀 Next Steps? Implement front-end integration and improve security with rate limiting and better email templates!
Top comments (0)