This project implements a minimal OTP-based authentication system using a Node.js backend and a React frontend.
The goal of the project is to demonstrate clear authentication flow, clean logic, and correct handling of edge cases, rather than UI design or production-level security.
🧠 High-Level Overview
The application follows a simple flow:
User enters email or phone number
Server generates and “sends” an OTP (mocked via console)
User enters OTP for verification
On successful verification, a session token is issued
Token is used to authenticate the user on protected routes
User can logout by clearing the token
🏗️ Architecture
Frontend (React + Tailwind)
|
| REST API calls
↓
Backend (Node.js + Express)
|
In-memory data store (JavaScript object)
No database is used
No external authentication services
State is kept intentionally simple
🔐 Authentication Flow
1. Request OTP
User submits email/phone
Backend:
Checks if user is temporarily blocked
Generates a 6-digit OTP
Stores OTP, expiry time, and attempt count in memory
Logs OTP to console (mock delivery)
- Verify OTP
User submits OTP
Backend:
Checks if OTP exists and is not expired
Tracks invalid attempts
Blocks user for 10 minutes after 3 failed attempts
On success, generates a random session token
- Authenticated Access
Frontend stores token in localStorage
Token is sent via Authorization: Bearer <token> header
Backend validates token and returns user info
4. Logout
Token is removed from localStorage
User is redirected to login page
🧩 Backend API Endpoints POST /auth/request-otp
Description:
Generates and sends OTP for a given identifier.
Request Body
{
"identifier": "test@gmail.com"
}
Response
{
"message": "OTP sent successfully"
}
POST /auth/verify-otp
Description:
Verifies OTP and issues a session token.
Request Body
{
"identifier": "test@gmail.com",
"otp": "123456"
}
Success Response
{
"message": "OTP verified successfully",
"token": "randomtokenvalue"
}
GET /auth/me
Description:
Validates token and returns authenticated user.
Headers
Authorization: Bearer <token>
Response
{
"identifier": "test@gmail.com",
"message": "User authenticated"
}
🧠 Assumptions Made
OTP validity: 5 minutes
Maximum OTP attempts: 3
Block duration after failures: 10 minutes
Users are auto-created on OTP request
OTP delivery is mocked using console logs
Session token is a random string (not JWT)
Data is stored in memory (resets on server restart)
🖥️ Frontend Pages
Page Purpose
Login Enter email/phone and request OTP
Verify OTP Enter OTP and verify
Welcome Protected page showing logged-in user
Routing handled using react-router-dom
Token persistence using localStorage
Styling intentionally minimal using Tailwind CSS
🚀 How to Run the Project Backend
cd Server
npm install
node server.js
Server runs on:
http://localhost:5000
Frontend
cd frontend
npm install
npm run dev
Frontend runs on: http://localhost:5173
🧪 Testing
All major scenarios were tested:
Correct OTP flow
Invalid OTP attempts
User blocking after 3 failures
Token validation
Logout and session clearing
Missing and invalid inputs
🎯 What This Project Demonstrates
Clear understanding of authentication flow
Clean and readable code
Proper handling of edge cases
Thoughtful assumptions
Focus on functionality over UI polish