6.7 KiB

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