System15 / hld.md
yamilogic's picture
Deploy SMTP Auth System to Hugging Face Space
50535d1
|
Raw
History Blame Contribute Delete
47 kB

Auth-System-SMTP β€” High-Level Design (HLD)


1. System Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          CLIENT (Browser)                          β”‚
β”‚                    React 18 + Vite (Port 5173)                     β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚ Register β”‚  β”‚  Login   β”‚  β”‚ Verify   β”‚  β”‚    Dashboard     β”‚  β”‚
β”‚   β”‚  Page    β”‚  β”‚  Page    β”‚  β”‚  Email   β”‚  β”‚ (Profile/Admin)  β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚        β”‚              β”‚              β”‚                  β”‚            β”‚
β”‚   β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚   β”‚                    AuthContext (State)                        β”‚ β”‚
β”‚   β”‚              + Axios Interceptors (Token)                    β”‚ β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚ HTTP/HTTPS
                               β”‚ Authorization: Bearer <token>
                               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       API SERVER (FastAPI)                          β”‚
β”‚                      (Port 8000, Uvicorn)                          β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                     Middleware Layer                         β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚
β”‚   β”‚  β”‚   CORS   β”‚  β”‚ Rate Limiter β”‚  β”‚  Request Logger      β”‚  β”‚  β”‚
β”‚   β”‚  β”‚ Middlewareβ”‚  β”‚ (60 req/min) β”‚  β”‚  (IP, method, path)  β”‚  β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                    Route Handlers                            β”‚  β”‚
β”‚   β”‚                                                              β”‚  β”‚
β”‚   β”‚  Auth Routes (/auth)          User Routes (/me, /admin)     β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚  β”‚
β”‚   β”‚  β”‚ register          β”‚         β”‚ GET    /me           β”‚      β”‚  β”‚
β”‚   β”‚  β”‚ verify-email      β”‚         β”‚ PUT    /me           β”‚      β”‚  β”‚
β”‚   β”‚  β”‚ login             β”‚         β”‚ DELETE /me           β”‚      β”‚  β”‚
β”‚   β”‚  β”‚ forgot-password   β”‚         β”‚ GET    /admin/users  β”‚      β”‚  β”‚
β”‚   β”‚  β”‚ reset-password    β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚  β”‚
β”‚   β”‚  β”‚ refresh           β”‚                                      β”‚  β”‚
β”‚   β”‚  β”‚ logout            β”‚                                      β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                      β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                     β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚   β”‚                   Core Services                              β”‚  β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚  β”‚
β”‚   β”‚  β”‚   Auth    β”‚  β”‚  Config   β”‚  β”‚   Database Manager    β”‚   β”‚  β”‚
β”‚   β”‚  β”‚ Service   β”‚  β”‚  Loader   β”‚  β”‚  (SQLAlchemy Engine)  β”‚   β”‚  β”‚
β”‚   β”‚  β”‚           β”‚  β”‚           β”‚  β”‚                       β”‚   β”‚  β”‚
β”‚   β”‚  β”‚ bcrypt    β”‚  β”‚ .env      β”‚  β”‚ SQLite3 Connection    β”‚   β”‚  β”‚
β”‚   β”‚  β”‚ JWT       β”‚  β”‚ variables β”‚  β”‚ Session Factory       β”‚   β”‚  β”‚
β”‚   β”‚  β”‚ SMTP Send β”‚  β”‚           β”‚  β”‚ Base (ORM)            β”‚   β”‚  β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                                    β”‚
             β–Ό                                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    SMTP SERVER       β”‚          β”‚         SQLite Database          β”‚
β”‚  (Gmail / Console)   β”‚          β”‚         (users.db)               β”‚
β”‚                      β”‚          β”‚                                  β”‚
β”‚  smtp.gmail.com      β”‚          β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  Port 587 (STARTTLS) β”‚          β”‚  β”‚   users    β”‚ β”‚revoked_tokensβ”‚ β”‚
β”‚                      β”‚          β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚  Sends OTP emails:   β”‚          β”‚                                  β”‚
β”‚  - Email Verify      β”‚          β”‚  Tables:                        β”‚
β”‚  - Password Reset    β”‚          β”‚  - users                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚  - revoked_tokens               β”‚
                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Component Architecture

2.1 Backend Components

backend/
β”œβ”€β”€ main.py              ← FastAPI app, CORS, rate limiting, middleware
β”œβ”€β”€ config.py            ← Loads .env variables via python-dotenv
β”œβ”€β”€ database.py          ← SQLAlchemy engine + session + Base
β”œβ”€β”€ models.py            ← ORM models: User, RevokedToken
β”œβ”€β”€ schemas.py           ← Pydantic request/response schemas
β”œβ”€β”€ auth.py              ← Password hashing, JWT, SMTP email
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ auth_routes.py   ← /auth endpoints (register, login, etc.)
β”‚   └── user_routes.py   ← /me and /admin endpoints
└── .env                 ← Environment variables (secrets)

Data Flow:

Request β†’ Middleware (CORS, Rate Limit, Logging)
       β†’ Route Handler (auth_routes / user_routes)
       β†’ Auth Service (validate token, hash password, send email)
       β†’ Database (SQLAlchemy ORM β†’ SQLite)
       β†’ Response (JSON)

2.2 Frontend Components

frontend/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.jsx                 ← Entry point, BrowserRouter
β”‚   β”œβ”€β”€ App.jsx                  ← Root component, all routes
β”‚   β”œβ”€β”€ index.css                ← Global styles (glassmorphism)
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   └── axios.js             ← Axios instance + interceptors
β”‚   β”œβ”€β”€ context/
β”‚   β”‚   └── AuthContext.jsx      ← Auth state management
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ Navbar.jsx           ← Navigation bar
β”‚   β”‚   └── ProtectedRoute.jsx   ← Route guard
β”‚   └── pages/
β”‚       β”œβ”€β”€ Register.jsx         ← Registration form
β”‚       β”œβ”€β”€ Login.jsx            ← Login form
β”‚       β”œβ”€β”€ VerifyEmail.jsx      ← OTP verification form
β”‚       └── Dashboard.jsx        ← User dashboard + admin panel

Component Hierarchy:

<App>
β”œβ”€β”€ <AuthProvider>           (Context)
β”‚   β”œβ”€β”€ <Navbar />
β”‚   β”œβ”€β”€ <Routes>
β”‚   β”‚   β”œβ”€β”€ /register     β†’ <Register />
β”‚   β”‚   β”œβ”€β”€ /login        β†’ <Login />
β”‚   β”‚   β”œβ”€β”€ /verify-email β†’ <VerifyEmail />
β”‚   β”‚   └── /dashboard    β†’ <ProtectedRoute> β†’ <Dashboard />
β”‚   β”‚   └── /             β†’ <Navigate to="/login" />

3. Authentication Flow Diagrams

3.1 Registration Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  β”‚                              β”‚  Server  β”‚                    β”‚  SMTP    β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚                                         β”‚                               β”‚
     β”‚  POST /auth/register                    β”‚                               β”‚
     β”‚  { username, email, password }          β”‚                               β”‚
     │────────────────────────────────────────▢│                               β”‚
     β”‚                                         β”‚                               β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€                               β”‚
     β”‚                           β”‚ Validate:   β”‚                               β”‚
     β”‚                           β”‚ - Email len β”‚                               β”‚
     β”‚                           β”‚ - Password  β”‚                               β”‚
     β”‚                           β”‚   strength  β”‚                               β”‚
     β”‚                           β”‚ - Uniquenessβ”‚                               β”‚
     β”‚                           └──────────────                               β”‚
     β”‚                                         β”‚                               β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€                               β”‚
     β”‚                           β”‚ bcrypt.hash β”‚                               β”‚
     β”‚                           β”‚ + OTP gen   β”‚                               β”‚
     β”‚                           β”‚ + Create    β”‚                               β”‚
     β”‚                           β”‚   User      β”‚                               β”‚
     β”‚                           └──────────────                               β”‚
     β”‚                                         β”‚                               β”‚
     β”‚                                         β”‚  Send OTP via SMTP            β”‚
     β”‚                                         │──────────────────────────────▢│
     β”‚                                         β”‚                               β”‚
     β”‚  200 OK (redirect to /verify-email)     β”‚                               β”‚
     │◀────────────────────────────────────────│                               β”‚
     β”‚                                         β”‚                               β”‚
     β”‚                                         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
     β”‚                                         β”‚  β”‚ Console fallback:      β”‚   β”‚
     β”‚                                         β”‚  β”‚ Print OTP if SMTP failsβ”‚   β”‚
     β”‚                                         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚

3.2 Login Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  β”‚                              β”‚  Server  β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚                                         β”‚
     β”‚  POST /auth/login                       β”‚
     β”‚  (OAuth2 form: username + password)     β”‚
     │────────────────────────────────────────▢│
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Look up     β”‚
     β”‚                           β”‚ user by     β”‚
     β”‚                           β”‚ username    β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ bcrypt      β”‚
     β”‚                           β”‚ .checkpw()  β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Check:      β”‚
     β”‚                           β”‚ - is_active β”‚
     β”‚                           β”‚ - is_verifiedβ”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Generate:   β”‚
     β”‚                           β”‚ - access_token  β”‚
     β”‚                           β”‚ - refresh_token β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚  200 OK                                 β”‚
     β”‚  { access_token, refresh_token }        β”‚
     │◀────────────────────────────────────────│
     β”‚                                         β”‚
     β”‚  Store in sessionStorage                β”‚
     β”‚  Set AuthContext user                   β”‚

3.3 Token Refresh Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  β”‚                              β”‚  Server  β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚                                         β”‚
     β”‚  API Request with expired access_token  β”‚
     │────────────────────────────────────────▢│
     β”‚                                         β”‚
     β”‚  401 Unauthorized                       β”‚
     │◀────────────────────────────────────────│
     β”‚                                         β”‚
     β”‚  Axios interceptor detects 401          β”‚
     β”‚                                         β”‚
     β”‚  POST /auth/refresh                     β”‚
     β”‚  { refresh_token }                      β”‚
     │────────────────────────────────────────▢│
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Decode JWT  β”‚
     β”‚                           β”‚ Check type  β”‚
     β”‚                           β”‚ == "refresh"β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Check if    β”‚
     β”‚                           β”‚ revoked     β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Revoke old  β”‚
     β”‚                           β”‚ refresh tokenβ”‚
     β”‚                           β”‚ (rotation)  β”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Issue new   β”‚
     β”‚                           β”‚ access +    β”‚
     β”‚                           β”‚ refresh pairβ”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚  200 OK                                 β”‚
     β”‚  { access_token, refresh_token }        β”‚
     │◀────────────────────────────────────────│
     β”‚                                         β”‚
     β”‚  Retry original request with new token  β”‚
     │────────────────────────────────────────▢│
     β”‚                                         β”‚
     β”‚  200 OK (success)                       β”‚
     │◀────────────────────────────────────────│

3.4 Logout Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Client  β”‚                              β”‚  Server  β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
     β”‚                                         β”‚
     β”‚  POST /auth/logout                      β”‚
     β”‚  { refresh_token }                      β”‚
     β”‚  Authorization: Bearer <access_token>   β”‚
     │────────────────────────────────────────▢│
     β”‚                                         β”‚
     β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
     β”‚                           β”‚ Insert both β”‚
     β”‚                           β”‚ tokens into β”‚
     β”‚                           β”‚ revoked_    β”‚
     β”‚                           β”‚ tokens tableβ”‚
     β”‚                           └──────────────
     β”‚                                         β”‚
     β”‚  200 OK                                 β”‚
     │◀────────────────────────────────────────│
     β”‚                                         β”‚
     β”‚  Clear sessionStorage                   β”‚
     β”‚  Set user = null                        β”‚
     β”‚  Redirect to /login                     β”‚

4. Data Models

4.1 Entity Relationship Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         users           β”‚          β”‚        revoked_tokens        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ id          INTEGER PK  β”‚          β”‚ id          INTEGER PK       β”‚
β”‚ username    VARCHAR UNI β”‚          β”‚ token       VARCHAR UNI      β”‚
β”‚ email       VARCHAR UNI β”‚          β”‚ revoked_at  DATETIME         β”‚
β”‚ password    VARCHAR     β”‚          β”‚ expires_at  DATETIME         β”‚
β”‚ is_active   BOOLEAN     β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ role        VARCHAR     β”‚
β”‚ created_at  DATETIME    β”‚          Relationship: One user can have
β”‚ is_verified BOOLEAN     β”‚          many revoked tokens (1:N)
β”‚ verification_code VARCHARβ”‚
β”‚ reset_code  VARCHAR     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

4.2 User Model Fields

Field Type Constraints Default Description
id Integer PK, auto-increment, indexed β€” Unique user identifier
username String(50) UNIQUE, NOT NULL, indexed β€” Login username
email String(120) UNIQUE, NOT NULL, indexed β€” User email address
password String(255) NOT NULL β€” bcrypt hashed password
is_active Boolean β€” True Account active status
role String(10) β€” "user" User role (user/admin)
created_at DateTime β€” datetime.utcnow() Registration timestamp
is_verified Boolean β€” False Email verified status
verification_code String(6) nullable None Registration OTP
reset_code String(6) nullable None Password reset OTP

4.3 RevokedToken Model Fields

Field Type Constraints Default Description
id Integer PK, auto-increment, indexed β€” Record identifier
token String(512) UNIQUE, NOT NULL, indexed β€” Full JWT string
revoked_at DateTime β€” datetime.utcnow() Revocation timestamp
expires_at DateTime NOT NULL β€” Token original expiry

5. Security Architecture

5.1 Authentication & Authorization Layers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    SECURITY LAYERS                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  Layer 1: Password Security                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ bcrypt hashing (salt + hash)                        β”‚   β”‚
β”‚  β”‚ Password strength validation (β‰₯8 chars, 1 letter,   β”‚   β”‚
β”‚  β”‚   1 digit)                                          β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 2: JWT Token Security                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Dual-token system (access 30min + refresh 7days)     β”‚   β”‚
β”‚  β”‚ Token rotation on refresh (old token revoked)        β”‚   β”‚
β”‚  β”‚ Token type validation (access vs refresh)            β”‚   β”‚
β”‚  β”‚ Revocation checking on every request                 β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 3: Email Verification                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ OTP-based email verification                        β”‚   β”‚
β”‚  β”‚ 6-digit numeric code                                β”‚   β”‚
β”‚  β”‚ Must verify before login                            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 4: Rate Limiting                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Global: 60 requests per 60 seconds per IP           β”‚   β”‚
β”‚  β”‚ HTTP 429 when exceeded                              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 5: CORS Protection                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Whitelist: localhost:5173, localhost:3000            β”‚   β”‚
β”‚  β”‚ Credentials allowed                                 β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 6: Role-Based Access Control                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Admin-only endpoints (/admin/users)                  β”‚   β”‚
β”‚  β”‚ User role checking in route handlers                 β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 7: Input Validation                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Pydantic schemas for all inputs                      β”‚   β”‚
β”‚  β”‚ Email validation (EmailStr)                          β”‚   β”‚
β”‚  β”‚ Field length constraints                             β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Layer 8: Error Handling                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Generic error messages (no stack trace leak)         β”‚   β”‚
β”‚  β”‚ Request logging for audit trail                      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

5.2 Token Lifecycle

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   User Login     β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚ Issue Access +   β”‚
                    β”‚ Refresh Tokens   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚              β”‚              β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”     β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Use Access     β”‚     β”‚     β”‚ Use Refresh    β”‚
     β”‚ Token (30min)  β”‚     β”‚     β”‚ Token (7days)  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚              β”‚              β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”     β”‚     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Token Expires  β”‚     β”‚     β”‚ Refresh Used   β”‚
     β”‚ (401 Response) β”‚     β”‚     β”‚ (Token Rotation)β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚              β”‚              β”‚
              β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
                     β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
              β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚ Issue New      β”‚
              β”‚ Send Refresh  β”‚     β”‚ Access+Refresh β”‚
              β”‚ Token to      β”‚     β”‚ Pair           β”‚
              β”‚ /auth/refresh β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Old Refresh   β”‚
              β”‚ Token Revoked β”‚
              β”‚ (stored in DB)β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

6. API Design

6.1 Request/Response Schemas

Register Request:

POST /auth/register
{
  "username": "string (3-50 chars)",
  "email": "string (valid email)",
  "password": "string (β‰₯8 chars, 1 letter, 1 digit)"
}

Register Response:

200 OK
{
  "message": "User registered successfully. Please verify your email."
}

Login Request:

POST /auth/login
Content-Type: application/x-www-form-urlencoded

username=string&password=string

Login Response:

200 OK
{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer"
}

Refresh Request:

POST /auth/refresh
{
  "refresh_token": "eyJ..."
}

Refresh Response:

200 OK
{
  "access_token": "eyJ...",
  "refresh_token": "eyJ..."
}

6.2 Error Response Format

401 Unauthorized
{
  "detail": "Invalid authentication credentials"
}

422 Validation Error
{
  "detail": [
    {
      "loc": ["body", "password"],
      "msg": "Password must be at least 8 characters with at least one letter and one digit",
      "type": "value_error"
    }
  ]
}

429 Too Many Requests
{
  "detail": "Too many requests. Please try again later."
}

7. SMTP Email System

7.1 Email Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Route       β”‚     β”‚  Auth        β”‚     β”‚  SMTP        β”‚
β”‚  Handler     │────▢│  Service     │────▢│  Server      β”‚
β”‚              β”‚     β”‚              β”‚     β”‚              β”‚
β”‚  send_email()β”‚     β”‚  smtplib     β”‚     β”‚  Gmail       β”‚
β”‚  called      β”‚     β”‚  STARTTLS    β”‚     β”‚  Port 587    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ (if SMTP not configured or fails)
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Console     β”‚
β”‚  Fallback    β”‚
β”‚  (print OTP) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

7.2 SMTP Configuration

Setting Value Purpose
Server smtp.gmail.com Gmail SMTP server
Port 587 STARTTLS encryption
Protocol STARTTLS Upgrades plain connection to TLS
Auth Username + App Password Gmail-specific authentication

7.3 Email Templates Sent

Email Verification:

Subject: Verify your email - Auth System

Hello {username},

Your verification code is: {otp_code}

This code will expire in 10 minutes.

If you did not register, please ignore this email.

Password Reset:

Subject: Password Reset Request - Auth System

Hello {username},

Your password reset code is: {otp_code}

This code will expire in 10 minutes.

If you did not request this, please ignore this email.

8. Frontend State Management

8.1 AuthContext Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     AuthContext                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  State:                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ user: null | { id, username, email, role, ... }     β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Methods:                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ login(username, password)                           β”‚   β”‚
β”‚  β”‚   β†’ POST /auth/login                                β”‚   β”‚
β”‚  β”‚   β†’ Store tokens in sessionStorage                  β”‚   β”‚
β”‚  β”‚   β†’ Fetch user profile                              β”‚   β”‚
β”‚  β”‚                                                     β”‚   β”‚
β”‚  β”‚ logout()                                            β”‚   β”‚
β”‚  β”‚   β†’ POST /auth/logout                               β”‚   β”‚
β”‚  β”‚   β†’ Clear sessionStorage                            β”‚   β”‚
β”‚  β”‚   β†’ Set user = null                                 β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚  Initialization (on mount):                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ 1. Check sessionStorage for access_token            β”‚   β”‚
β”‚  β”‚ 2. If exists β†’ GET /me to validate                  β”‚   β”‚
β”‚  β”‚ 3. If valid β†’ set user state                        β”‚   β”‚
β”‚  β”‚ 4. If invalid β†’ clear session, set user = null      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

8.2 Axios Interceptor Chain

Request Flow:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  API     │───▢│   Request    │───▢│   Server     │───▢│ Response β”‚
β”‚  Call    β”‚    β”‚ Interceptor  β”‚    β”‚              β”‚    β”‚          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
                  β”‚                                           β”‚
                  β”‚ Attach Bearer token                       β”‚
                  β”‚ from sessionStorage                       β”‚
                                                           β”‚
                                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                              β”‚  Response Interceptor  β”‚
                                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                           β”‚
                                              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                              β”‚  If 401:               β”‚
                                              β”‚  1. POST /auth/refresh β”‚
                                              β”‚  2. Update tokens      β”‚
                                              β”‚  3. Retry request      β”‚
                                              β”‚  4. If fail β†’ /login   β”‚
                                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

9. Deployment Architecture

9.1 Development Setup

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Development Environment             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                   β”‚
β”‚  Terminal 1: Backend                              β”‚
β”‚  $ cd backend                                     β”‚
β”‚  $ source .venv/bin/activate                      β”‚
β”‚  $ uvicorn main:app --reload --port 8000          β”‚
β”‚                                                   β”‚
β”‚  Terminal 2: Frontend                             β”‚
β”‚  $ cd frontend                                    β”‚
β”‚  $ npm run dev                                    β”‚
β”‚  β†’ Vite dev server on http://localhost:5173       β”‚
β”‚                                                   β”‚
β”‚  Database: SQLite (auto-created)                  β”‚
β”‚  Email: Console fallback (no SMTP needed)         β”‚
β”‚                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

9.2 Production Recommendations

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Production Architecture                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚   Nginx     │───▢│  Uvicorn    │───▢│   PostgreSQL        β”‚  β”‚
β”‚  β”‚   (Reverse  β”‚    β”‚  (Gunicorn  β”‚    β”‚   (or MySQL)        β”‚  β”‚
β”‚  β”‚    Proxy)   β”‚    β”‚   Workers)  β”‚    β”‚                     β”‚  β”‚
β”‚  β”‚   Port 443  β”‚    β”‚   Port 8000 β”‚    β”‚   Port 5432         β”‚  β”‚
β”‚  β”‚   HTTPS     β”‚    β”‚             β”‚    β”‚                     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚        β”‚                                         β”‚                β”‚
β”‚        β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚                β”‚
β”‚        β”‚            β”‚   Redis     β”‚             β”‚                β”‚
β”‚        β”‚            β”‚   (Cache +  │◀─────────────                β”‚
β”‚        β”‚            β”‚    Rate     β”‚             β”‚                β”‚
β”‚        β”‚            β”‚   Limiting) β”‚             β”‚                β”‚
β”‚        β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚                β”‚
β”‚        β”‚                                         β”‚                β”‚
β”‚        β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚                β”‚
β”‚        └───────────▢│   Static    β”‚             β”‚                β”‚
β”‚                     β”‚   Files     β”‚             β”‚                β”‚
β”‚                     β”‚   (React    β”‚             β”‚                β”‚
β”‚                     β”‚    Build)   β”‚             β”‚                β”‚
β”‚                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚                β”‚
β”‚                                                   β”‚                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

10. Environment Configuration

Variable Development Production Purpose
SECRET_KEY super_secret_dev_key... Strong random 256-bit key JWT signing
ALGORITHM HS256 HS256 or RS256 JWT algorithm
ACCESS_TOKEN_EXPIRE_MINUTES 30 15 Shorter in prod
REFRESH_TOKEN_EXPIRE_DAYS 7 7 Refresh token TTL
DATABASE_URL sqlite:///./users.db postgresql://... Database
SMTP_SERVER smtp.gmail.com smtp.gmail.com Email server
SMTP_PORT 587 587 Email port
SMTP_USER user@gmail.com noreply@domain.com Email sender
SMTP_PASSWORD app_password app_password Email auth

11. Future Improvements

High Priority

  • Add .gitignore (exclude .env, users.db, __pycache__, node_modules)
  • Use secrets module for OTP generation (cryptographic randomness)
  • Add per-account brute-force lockout (e.g., 5 failed attempts β†’ 15min lock)
  • Move to PostgreSQL for production use

Medium Priority

  • Add Docker + docker-compose for containerized deployment
  • Implement email rate limiting (prevent OTP spam)
  • Add CSRF protection
  • Add comprehensive unit and integration tests
  • Implement account deletion with cascade (revoke all tokens)

Low Priority

  • Add OAuth2 social login (Google, GitHub)
  • Implement 2FA (TOTP-based)
  • Add admin dashboard for user management
  • Implement audit logging
  • Add API versioning (v1/, v2/)