I built this project to implement a secure login system with Multi-Factor Authentication (MFA) using the MERN stack.
The app requires users to log in with email + password and then verify a 6-digit OTP sent to their email.
👉 Backend is deployed on Render
👉 Frontend is deployed on Vercel
👉 Database is hosted on MongoDB Atlas
- User authentication with email + password
- Email-based OTP verification (6 digits)
- Resend OTP option with a countdown timer
- Protected dashboard with session handling
- Logout that also prevents back/forward navigation into dashboard
- Cloud-hosted MongoDB for persistence
- Frontend: React, React Router, Vercel
- Backend: Node.js, Express, Mongoose
- Database: MongoDB Atlas
- Auth/Email Service: Mailtrap SMTP
- Deployment: Render (backend) + Vercel (frontend)
mfa-mern/
│── client/ # React frontend (Vercel)
│ └── src/
│ ├── components/ # Login, Dashboard, etc.
│ ├── config.js # API base URL
│ └── App.js
│
│── server/ # Express backend (Render)
│ ├── routes/ # Authentication routes
│ ├── models/ # User model
│ ├── server.js # Main server file
│ └── .env # Environment variables
│
│── README.md
git clone https://github.com/<my-username>/mfa-mern.git
cd mfa-merncd server
npm installI created a .env file inside server/:
PORT=5000
MONGO_URI=your_mongodb_atlas_uri
MAILTRAP_USER=your_mailtrap_username
MAILTRAP_PASS=your_mailtrap_passwordRun backend locally:
npm start➡️ Runs on http://localhost:5000
cd client
npm installI created a .env file inside client/:
REACT_APP_API_BASE_URL=http://localhost:5000Run frontend locally:
npm start➡️ Runs on http://localhost:3000
- Pushed repo to GitHub
- On Render, created a Web Service
- Connected GitHub → selected
server/ - Added environment variables from
.env - Deployed → got live API URL like:
https://mfa-mern-xxxxx.onrender.com
- Went to Vercel
- Imported project → selected
client/ - Added environment variable:
REACT_APP_API_BASE_URL=https://mfa-mern-xxxxx.onrender.com
- Deployed → got live frontend URL like:
https://mfa-mern.vercel.app
PORT=5000
MONGO_URI=your_mongodb_atlas_uri
MAILTRAP_USER=your_mailtrap_username
MAILTRAP_PASS=your_mailtrap_password
REACT_APP_API_BASE_URL=https://mfa-mern-xxxxx.onrender.com
- Enter Email + Password
- Receive OTP in email
- Enter 6-digit OTP
- Redirected to Dashboard ✅
- If logged out or going back/forward → redirected to Login
POST /auth/register
{
"email": "test@example.com",
"password": "123456"
}POST /auth/login
{
"email": "test@example.com",
"password": "123456"
}POST /auth/verify-otp
{
"email": "test@example.com",
"otp": "123456"
}If anyone wants to extend this project (e.g., JWT, Google Authenticator, SMS OTP), feel free to fork and PR!
MIT License © 2025 — Built by Surya Panduri 🙂