208 lines
6.7 KiB
Markdown
208 lines
6.7 KiB
Markdown
|
|
# 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 |
|