Authy is a complete, production-ready, and visually stunning MERN Stack Authentication & Multi-Step Verification System. It features a modern React/Next.js frontend styled with a sleek dark glassmorphic interface, backed by an Express/Node.js API connected to MongoDB.
This repository serves as a boilerplate for secure user onboarding flows with robust client-side state management and route security.
- Single Source of Truth (Zustand): Client-side state managed globally using Zustand and persisted in
localStorageto survive page refreshes. - Header Interceptor (Axios): A centralized Axios instance with a request interceptor that automatically reads the JWT session token from the Zustand store and injects it as a
Bearer <token>header. - Auto-Routing Guards: A high-order route guard component (
ProtectedRoute) that enforces page-level access. If the user is unauthenticated, they are routed to/login. If authenticated, the system auto-routes them through the multi-step verification funnel (Email -> Phone -> Dashboard). - Time-Limited OTP Verification (10 Minutes): Time-limited verification codes generated for both email and phone checks, with validation checking timestamps for expiry.
- Password Reset Lifecycles (1 Hour): Secure password recovery generating cryptographically secure tokens valid for 1 hour.
- Premium Glassmorphism Design: Forms and dashboards styled with deep slates, custom typography, hover transitions, and glowing ambient gradients using Tailwind CSS.
Authy/
├── backend/ # Express REST API Server
│ ├── controllers/ # Authentication routing functions (authController.js)
│ ├── middleware/ # JWT extraction & route protection (auth.js)
│ ├── models/ # MongoDB Mongoose Schemas (User.js)
│ ├── package.json # Server package manifest
│ └── server.js # Main server execution script
│
└── frontend/ # Next.js Pages Client
├── src/
│ ├── components/ # Route guards (ProtectedRoute)
│ ├── lib/ # Centralized Axios API client
│ ├── store/ # Zustand persistent store hook
│ ├── styles/ # Global Tailwind directives
│ └── pages/ # Core authentication routes & page components
├── package.json # Client package manifest
├── tailwind.config.js # Tailwind layout settings
└── next.config.mjs # Next.js runtime config
- Node.js (v18.0.0 or higher recommended)
- MongoDB (Running locally on
mongodb://127.0.0.1:27017or using a MongoDB Atlas URI)
- Navigate into the backend directory:
cd backend - Install dependencies:
npm install
- Create a
.envfile in thebackendfolder and add your credentials:PORT=5000 MONGO_URI=mongodb://127.0.0.1:27017/mern-auth-db JWT_SECRET=your_super_secure_jwt_secret_key_here
- Start the backend server:
The server runs on
npm run dev
http://localhost:5000
- Navigate into the frontend directory:
cd ../frontend - Install dependencies:
npm install
- Start the Next.js dev server:
The client runs on
npm run dev
http://localhost:3000
All API endpoints are prefixed with /api. Protected routes require a valid JWT token in the Authorization header.
| Endpoint | Method | Authentication | Payload Schema | Description |
|---|---|---|---|---|
/status |
GET | None | None | Checks API status and database availability. |
/auth/signup |
POST | None | { name, email, phone, password } |
Registers a new account, generates a 10-minute email OTP, and returns a JWT. |
/auth/login |
POST | None | { email, password } |
Authenticates credentials and returns user details with a JWT. |
/auth/me |
GET | JWT | None | Fetches the current authenticated user's profile metadata. |
/auth/verify-email |
POST | JWT | { otp } |
Validates email OTP, updates status, and issues a 10-minute phone OTP. |
/auth/verify-phone |
POST | JWT | { otp } |
Validates phone OTP and completes the onboarding verification checklist. |
/auth/forgot-password |
POST | None | { email } |
Generates a 1-hour secure password reset token. |
/auth/reset-password |
POST | None | { token, password } |
Validates the recovery token and updates the user's password. |
To make local testing and integration testing simple, a developer helper endpoint is exposed when running in non-production environments:
GET http://localhost:5000/api/auth/test-otp/:emailThis returns active OTPs and reset tokens for any registered email directly on the screen, allowing you to run verification cycles without configuring external SMS/Email dispatchers (like Twilio or Nodemailer):
{
"emailVerificationOtp": "166863",
"phoneVerificationOtp": null,
"resetPasswordToken": "ab93f234fdcb74ebf02b8eb0bf5e71de7ce6b3df"
}The frontend uses Zustand with the persist middleware. This maps states directly into the browser's localStorage to avoid session loss:
{
user: { id, name, email, phone, isEmailVerified, isPhoneVerified },
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
isAuthenticated: true,
isEmailVerified: true,
isPhoneVerified: true
}All frontend components are crafted using Tailwind CSS and integrate custom variables defined in globals.css:
- Glassmorphism: Panels use blurred, semi-transparent backgrounds with a subtle white border
rgba(255, 255, 255, 0.07)to stand out against glowing ambient backgrounds. - Ambient Lighting: Layout wrappers load animated blurred glowing indigo and violet orbs dynamically positioned in the background.
- Typography: Outfit and Plus Jakarta Sans are pre-loaded from Google Fonts for a clean, premium font face.