# Auth Module Authentication and authorization for the Customer Portal. ## Architecture Overview ``` auth/ ├── application/ # Orchestration layer │ ├── auth.facade.ts # Main entry point for auth operations │ ├── auth-login.service.ts │ └── auth-health.service.ts ├── decorators/ │ └── public.decorator.ts # @Public, @PublicNoSession, @OptionalAuth ├── presentation/http/ │ ├── auth.controller.ts # Login, signup, password endpoints │ ├── get-started.controller.ts # OTP-based onboarding │ ├── guards/ │ │ ├── global-auth.guard.ts # JWT validation (APP_GUARD) │ │ ├── local-auth.guard.ts # Credential validation │ │ └── failed-login-throttle.guard.ts │ └── interceptors/ │ └── login-result.interceptor.ts └── infra/ # Infrastructure services ├── token/ # JWT & token management ├── otp/ # OTP & session management ├── rate-limiting/ # Auth-specific rate limits └── workflows/ # Multi-step auth flows ``` ## Security Features ### Token Management | Feature | Description | | ----------------------------- | --------------------------------------- | | **Access Token** | 15-min expiry, HS256 HMAC-signed | | **Refresh Token** | 7-day expiry with family-based rotation | | **Single-Use Password Reset** | Redis-tracked tokens prevent replay | | **Token Blacklist** | Immediate revocation on logout | ### OTP Security | Feature | Description | | ----------------------- | ----------------------------------------------- | | **Code Generation** | Cryptographically secure 6-digit codes | | **Expiration** | 10 minutes (configurable) | | **Max Attempts** | 3 attempts before invalidation | | **Fingerprint Binding** | Logs warning if verified from different context | ### Rate Limiting | Endpoint | Limit | Window | | -------------- | ----------- | ---------- | | Login | 5 attempts | 15 minutes | | Signup | 5 attempts | 15 minutes | | Password Reset | 5 attempts | 15 minutes | | OTP Send | 5 codes | 5 minutes | | OTP Verify | 10 attempts | 5 minutes | ## Authentication Flows ### 1. Login Flow ``` POST /auth/login │ ▼ LocalAuthGuard (validates credentials) │ ▼ FailedLoginThrottleGuard (rate limiting) │ ▼ AuthFacade.login() │ ├─► Generate token pair ├─► Set httpOnly cookies └─► Return user + session metadata ``` ### 2. Password Reset Flow (Single-Use) ``` POST /auth/request-password-reset │ ▼ PasswordResetTokenService.create() │ ├─► Generate JWT with tokenId ├─► Store tokenId in Redis (15-min TTL) └─► Send email with reset link POST /auth/reset-password │ ▼ PasswordResetTokenService.consume() │ ├─► Verify JWT signature & expiry ├─► Check tokenId exists in Redis ├─► Delete tokenId (single-use enforcement) └─► If already deleted → "Token already used" ``` ### 3. Get Started Flow (OTP) ``` POST /auth/get-started/send-code │ ▼ OtpService.generateAndStore(email, fingerprint) │ ├─► Generate 6-digit code ├─► Store in Redis with fingerprint └─► Send email POST /auth/get-started/verify-code │ ▼ OtpService.verify(email, code, fingerprint) │ ├─► Check fingerprint (warn if mismatch) ├─► Validate code └─► Determine account status Account Status: ├─► PORTAL_EXISTS → Redirect to login ├─► WHMCS_UNMAPPED → Redirect to migration ├─► SF_UNMAPPED → Complete account └─► NEW_CUSTOMER → Full signup ``` ## Configuration ### Environment Variables ```bash # JWT Configuration JWT_SECRET= # Required: HMAC signing key JWT_SECRET_PREVIOUS= # Optional: Previous keys for rotation (comma-separated) JWT_ISSUER= # Optional: Token issuer claim JWT_AUDIENCE= # Optional: Token audience claim # Token Expiry ACCESS_TOKEN_EXPIRY=900 # 15 minutes (seconds) REFRESH_TOKEN_EXPIRY=604800 # 7 days (seconds) PASSWORD_RESET_TTL_SECONDS=900 # 15 minutes # OTP Configuration OTP_TTL_SECONDS=600 # 10 minutes OTP_MAX_ATTEMPTS=3 # Max verification attempts # Rate Limiting LOGIN_RATE_LIMIT_LIMIT=5 # Max attempts LOGIN_RATE_LIMIT_TTL=900000 # Window in ms (15 min) LOGIN_CAPTCHA_AFTER_ATTEMPTS=3 # CAPTCHA threshold # Redis Behavior AUTH_ALLOW_REDIS_TOKEN_FAILOPEN=false # Continue without Redis AUTH_REQUIRE_REDIS_FOR_TOKENS=false # Strict Redis requirement AUTH_MAINTENANCE_MODE=false # Disable auth service ``` ## Route Protection ### Decorators ```typescript // Anyone can access, optionally attach user if token exists @Public() // Strict public - no session attachment, no cookies read @PublicNoSession() // No token = allow (user=null), invalid token = 401 @OptionalAuth() // Default: requires valid access token (401 if missing/invalid) ``` ### Guard Behavior | Decorator | Missing Token | Invalid Token | Valid Token | | ------------------ | ------------- | ------------- | --------------- | | (none) | 401 | 401 | ✓ user attached | | @Public() | ✓ | ✓ | ✓ user attached | | @PublicNoSession() | ✓ | ✓ | ✓ no user | | @OptionalAuth() | ✓ null user | 401 | ✓ user attached | ## External Integrations The auth module integrates with: - **WHMCS**: Account discovery, client creation, credential validation - **Salesforce**: Account lookup, portal status updates - **Redis**: Token storage, OTP codes, session management - **Email (SendGrid)**: OTP codes, password reset links ## Directory Reference | Directory | Purpose | | --------------------------- | ---------------------------------------------- | | `infra/token/` | JWT signing, refresh token rotation, blacklist | | `infra/otp/` | OTP codes, get-started sessions | | `infra/rate-limiting/` | Auth-specific rate limiters | | `infra/workflows/` | Multi-step flows (signup, password, migration) | | `presentation/http/guards/` | Request validation, token verification |