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
# 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
// 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 |