A comprehensive, production-ready authentication system built with the MERN stack (MongoDB, Express.js, React, Node.js) featuring secure session management, email verification, password reset functionality, and modern UI/UX.
- Overview
- Architecture
- Features
- Technology Stack
- System Design
- Authentication Flow
- Security Features
- API Documentation
- Installation & Setup
- Environment Variables
- Usage Examples
- Contributing
This authentication system implements a robust, secure authentication mechanism with the following key components:
- Backend: Node.js/Express.js API with TypeScript
- Frontend: React with Chakra UI and React Query
- Database: MongoDB with Mongoose ODM
- Authentication: JWT-based with refresh tokens
- Email Service: Resend for email verification and password reset
- Security: bcrypt password hashing, secure cookies, CORS protection
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Frontend β β Backend β β Database β
β (React) βββββΊβ (Express) βββββΊβ (MongoDB) β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β
β β β
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Chakra UI β β JWT Tokens β β Collections β
β React Query β β Middleware β β - Users β
β React Router β β Controllers β β - Sessions β
βββββββββββββββββββ βββββββββββββββββββ β - Verificationβ
βββββββββββββββββββ
- User Registration with email verification
- Secure Login with password hashing
- JWT-based Authentication with access and refresh tokens
- Session Management with device tracking
- Password Reset via email
- Email Verification for new accounts
- Automatic Token Refresh on frontend
- Logout with session cleanup
- bcrypt Password Hashing (salt rounds: 12)
- HTTP-only Secure Cookies for token storage
- CORS Protection with origin validation
- Rate Limiting for password reset requests
- Session Expiration (30 days default)
- Token Expiration (Access: 15min, Refresh: 30 days)
- Input Validation with Zod schemas
- Error Handling with custom error codes
- Modern UI with Chakra UI components
- Responsive Design for all devices
- Real-time State Management with React Query
- Protected Routes with authentication guards
- Session Management UI showing active devices
- Form Validation and error handling
- Loading States and user feedback
- Node.js - JavaScript runtime
- Express.js - Web framework
- TypeScript - Type safety
- MongoDB - NoSQL database
- Mongoose - ODM for MongoDB
- JWT - JSON Web Tokens
- bcrypt - Password hashing
- Zod - Schema validation
- Resend - Email service
- Cookie-parser - Cookie handling
- CORS - Cross-origin resource sharing
- React 18 - UI library
- Vite - Build tool
- Chakra UI - Component library
- React Query - Data fetching
- React Router - Client-side routing
- Axios - HTTP client
- Framer Motion - Animations
erDiagram
User {
ObjectId _id PK
String email UK
String password
Boolean verified
Date createdAt
Date updatedAt
}
Session {
ObjectId _id PK
ObjectId userId FK
String userAgent
Date createdAt
Date expiresAt
}
VerificationCode {
ObjectId _id PK
ObjectId userId FK
String type
Date createdAt
Date expiresAt
}
User ||--o{ Session : "has"
User ||--o{ VerificationCode : "has"
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend
participant D as Database
participant E as Email Service
Note over U,E: Registration Flow
U->>F: Fill registration form
F->>B: POST /auth/register
B->>D: Create user & verification code
B->>E: Send verification email
B->>F: Return user data & tokens
F->>U: Set cookies & redirect
Note over U,E: Login Flow
U->>F: Fill login form
F->>B: POST /auth/login
B->>D: Verify credentials
B->>D: Create session
B->>F: Return tokens
F->>U: Set cookies & redirect
Note over U,E: Protected Route Access
U->>F: Access protected route
F->>B: GET /user (with access token)
B->>B: Verify JWT token
B->>D: Get user data
B->>F: Return user data
F->>U: Display protected content
Note over U,E: Token Refresh Flow
F->>B: GET /auth/refresh (with refresh token)
B->>B: Verify refresh token
B->>D: Check session validity
B->>F: Return new access token
F->>U: Update cookies
graph TD
A[User Login] --> B[Create Session]
B --> C[Generate Access Token]
B --> D[Generate Refresh Token]
C --> E[Set HTTP-only Cookies]
D --> E
E --> F[Session Active]
F --> G{Token Expired?}
G -->|Yes| H[Use Refresh Token]
G -->|No| I[Continue Session]
H --> J{Refresh Token Valid?}
J -->|Yes| K[Generate New Access Token]
J -->|No| L[Redirect to Login]
K --> F
I --> M[Session Expires in 30 Days]
M --> N[Auto Logout]
- User fills registration form (email, password, confirm password)
- Frontend validates input and sends to
/auth/register
- Backend validates data with Zod schemas
- Checks if email already exists
- Hashes password with bcrypt
- Creates user record in database
- Generates email verification code
- Sends verification email via Resend
- Creates session and generates JWT tokens
- Sets secure HTTP-only cookies
- Returns user data (without password)
- User clicks verification link in email
- Frontend extracts verification code from URL
- Makes request to
/auth/email/verify/:code
- Backend validates verification code
- Updates user's
verified
status totrue
- Deletes verification code from database
- Returns success message
- User enters email and password
- Frontend sends credentials to
/auth/login
- Backend finds user by email
- Compares password hash using bcrypt
- Creates new session with user agent
- Generates access and refresh tokens
- Sets secure cookies
- Returns success message
- Frontend makes API request with access token
- Backend middleware validates JWT token
- Extracts user ID and session ID from token
- Checks if session exists and is valid
- Attaches user data to request object
- Allows access to protected resource
- Frontend detects 401 error with
InvalidAccessToken
code - Automatically calls
/auth/refresh
with refresh token - Backend validates refresh token
- Checks session validity and expiration
- Generates new access token
- Optionally generates new refresh token if expiring soon
- Updates cookies and continues original request
- User requests password reset via email
- Backend validates email and creates reset code
- Sends password reset email with secure link
- User clicks link and enters new password
- Backend validates reset code and updates password
- Deletes all user sessions (force logout from all devices)
- Clears authentication cookies
- bcrypt Hashing: Passwords are hashed with bcrypt using 12 salt rounds
- Pre-save Middleware: Automatic password hashing before saving to database
- Password Validation: Minimum 6 characters required
- JWT Tokens: Access tokens (15min) and refresh tokens (30 days)
- HTTP-only Cookies: Tokens stored in secure, HTTP-only cookies
- SameSite Policy: Cookies set with
strict
same-site policy - Secure Flag: Cookies marked as secure in production
- Session Tracking: Each login creates a new session with user agent
- Session Expiration: Sessions expire after 30 days
- Session Management: Users can view and delete active sessions
- Force Logout: Password reset invalidates all sessions
- CORS Protection: Configured with specific origin and credentials
- Input Validation: All inputs validated with Zod schemas
- Error Handling: Custom error codes and messages
- Rate Limiting: Password reset requests limited to prevent abuse
Register a new user account.
Request Body:
{
"email": "user@example.com",
"password": "password123",
"confirmPassword": "password123"
}
Response:
{
"_id": "user_id",
"email": "user@example.com",
"verified": false,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
Authenticate user and create session.
Request Body:
{
"email": "user@example.com",
"password": "password123"
}
Response:
{
"message": "Login SuccessFull"
}
Refresh access token using refresh token.
Response:
{
"message": "Access token refreshed"
}
Logout user and invalidate session.
Response:
{
"message": "Logout successfull"
}
Verify email address using verification code.
Response:
{
"message": "Email was successfully verified"
}
Send password reset email.
Request Body:
{
"email": "user@example.com"
}
Response:
{
"message": "Password reset email send"
}
Reset password using verification code.
Request Body:
{
"password": "newpassword123",
"verificationCode": "verification_code_id"
}
Response:
{
"message": "Password reset successfull"
}
Get current user information.
Response:
{
"_id": "user_id",
"email": "user@example.com",
"verified": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
Get all active sessions for current user.
Response:
[
{
"_id": "session_id",
"userAgent": "Mozilla/5.0...",
"createdAt": "2024-01-01T00:00:00.000Z",
"isCurrent": true
}
]
Delete specific session.
Response:
{
"message": "Session removed"
}
- Node.js (v18 or higher)
- MongoDB (local or cloud)
- Resend account for email service
- Clone the repository
git clone <repository-url>
cd mern-authentication/backend
- Install dependencies
npm install
- Set up environment variables
cp .env.example .env
# Edit .env with your configuration
- Start development server
npm run dev
- Navigate to frontend directory
cd ../frontend
- Install dependencies
npm install
- Set up environment variables
cp .env.example .env
# Edit .env with your API URL
- Start development server
npm run dev
# Database
MONGO_URI=mongodb://localhost:27017/auth-app
# Server
NODE_ENV=development
PORT=4004
APP_ORIGIN=http://localhost:5173
# JWT Secrets
JWT_SECRET=your-super-secret-jwt-key
JWT_REFRESH_SECRET=your-super-secret-refresh-key
# Email Service (Resend)
EMAIL_SENDER=noreply@yourdomain.com
RESEND_API_KEY=your-resend-api-key
VITE_API_URL=http://localhost:4004
import useAuth from "./hooks/useAuth";
function Profile() {
const { user, isLoading } = useAuth();
if (isLoading) return <div>Loading...</div>;
if (!user) return <div>Please login</div>;
return <div>Welcome, {user.email}!</div>;
}
import { login, register, getUser } from "./lib/api";
// Login
const handleLogin = async (email, password) => {
try {
await login({ email, password });
// Redirect or update state
} catch (error) {
console.error("Login failed:", error);
}
};
// Register
const handleRegister = async (email, password, confirmPassword) => {
try {
const user = await register({ email, password, confirmPassword });
// Handle successful registration
} catch (error) {
console.error("Registration failed:", error);
}
};
// Get user data
const { user } = useAuth();
import { Navigate } from "react-router-dom";
import useAuth from "./hooks/useAuth";
function ProtectedRoute({ children }) {
const { user, isLoading } = useAuth();
if (isLoading) return <div>Loading...</div>;
if (!user) return <Navigate to="/login" replace />;
return children;
}
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the ISC License.
- Chakra UI for the beautiful component library
- React Query for efficient data fetching
- Resend for reliable email delivery
- MongoDB for the flexible database
- Express.js for the robust web framework
Note: This is a production-ready authentication system with comprehensive security features. Make sure to customize the environment variables and security settings according to your specific requirements before deploying to production.