# 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 ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 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:** ``` ├── (Context) │ ├── │ ├── │ │ ├── /register → │ │ ├── /login → │ │ ├── /verify-email → │ │ └── /dashboard → │ │ └── / → ``` --- ## 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 │ │────────────────────────────────────────▶│ │ │ │ ┌─────────────┤ │ │ 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:** ```json POST /auth/register { "username": "string (3-50 chars)", "email": "string (valid email)", "password": "string (≥8 chars, 1 letter, 1 digit)" } ``` **Register Response:** ```json 200 OK { "message": "User registered successfully. Please verify your email." } ``` **Login Request:** ```json POST /auth/login Content-Type: application/x-www-form-urlencoded username=string&password=string ``` **Login Response:** ```json 200 OK { "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer" } ``` **Refresh Request:** ```json POST /auth/refresh { "refresh_token": "eyJ..." } ``` **Refresh Response:** ```json 200 OK { "access_token": "eyJ...", "refresh_token": "eyJ..." } ``` ### 6.2 Error Response Format ```json 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/)