Skip to content

Latest commit

 

History

History
232 lines (182 loc) · 8.5 KB

File metadata and controls

232 lines (182 loc) · 8.5 KB

BE-045: CORS Allowlist Configuration - Implementation Summary

Overview

Successfully implemented production-grade CORS allowlist configuration for ChronoPay-Backend with comprehensive testing, documentation, and security features. The implementation replaces the permissive default cors() middleware with a secure, configurable allowlist-based solution.

Implementation Details

1. Core Modules Created

Purpose: CORS configuration management and origin validation logic

Key Components:

  • CORSConfig interface: Defines CORS configuration structure
  • getCORSConfig(): Loads configuration from environment variables with environment-based defaults
  • isOriginAllowed(): Validates origins against allowlist with pattern matching support
  • matchOriginPattern(): Implements secure wildcard pattern matching for subdomains
  • validateCORSConfig(): Comprehensive configuration validation with security constraints
  • Helper functions for parsing environment variables (CSV lists, booleans, numbers)

Security Features:

  • Wildcard-only patterns (*) are rejected
  • Multiple wildcards in single pattern are rejected
  • Wildcards must be followed by a dot (prevents *.com style patterns)
  • All origins validated as valid URLs
  • Empty allowlist for production environment by default

Purpose: Express middleware for CORS validation

Key Components:

  • createCORSMiddleware(): Creates Express middleware that enforces CORS allowlist
  • Proper preflight (OPTIONS) request handling
  • Headers only set for allowed origins (prevents information leakage)
  • Returns 403 for disallowed preflight requests

2. Files Modified

  • Replaced permissive cors() middleware with createCORSMiddleware(corsConfig)
  • Added CORS configuration loading and validation on startup
  • Removed direct cors import, added config and middleware imports
  • Updated ts-jest configuration to support isolatedModules: true
  • Enhanced TypeScript compilation options for ESM modules
  • Fixed import to include .js extension for ESM compatibility

3. Tests Created

src/tests/cors.test.ts - 52 comprehensive tests

Test Coverage by Category:

  1. Origin Validation Tests (19 tests)

    • Exact origin matching
    • Wildcard pattern matching (including nested subdomains)
    • Case sensitivity for schemes
    • Port number handling
    • Invalid URL rejection
    • Empty/undefined/whitespace origin handling
  2. Configuration Loading Tests (9 tests)

    • Environment-based defaults (development vs production)
    • Loading from environment variables (origins, methods, headers, credentials, maxAge)
    • Whitespace trimming from CSV lists
    • Invalid value handling (graceful fallbacks)
  3. Configuration Validation Tests (11 tests)

    • Valid configuration acceptance
    • Invalid configuration rejection (missing fields, wrong types)
    • Wildcard pattern validation
    • URL validation
    • maxAge validation (negative values, non-numbers)
    • Warning behavior for empty allowlists
  4. Middleware Tests (13 tests)

    • Preflight requests: OPTIONS handling, CORS headers, disallowed origin handling
    • Simple requests: GET/POST with CORS headers, disallowed origins
    • Credentials handling: Conditional credentials header based on configuration
    • Edge cases: Missing Origin header, empty allowlist, middleware chaining

Coverage Metrics:

  • Overall Statements: 98.68%
  • Overall Branches: 92.68%
  • Overall Functions: 91.66%
  • Overall Lines: 98.66%
  • Middleware CORS: 100% coverage across all metrics
  • Config CORS: 98.36% statements, 91.89% branches, 90% functions

4. Documentation Created

Comprehensive guide covering:

  • Feature Overview: What the implementation provides
  • Configuration Guide: Environment variables, defaults by environment
  • Origin Matching Rules: Exact matches, wildcard patterns, security constraints
  • Security Considerations: Design assumptions, failure modes, risk mitigation
  • Implementation Details: How each component works internally
  • Testing Information: What's tested and how to run tests
  • API Reference: Complete documentation of all exported functions
  • Troubleshooting: Common issues and solutions

Key Features Implemented

Secure by Default

  • No origins allowed until explicitly configured
  • Production environment has empty allowlist by default
  • Invalid origins are rejected with proper error handling

Flexible Configuration

  • Environment variable-based configuration
  • Support for wildcard patterns for dynamic subdomains
  • Configurable HTTP methods, headers, credentials, and cache age
  • Easy to set up different configurations per environment

Robust Pattern Matching

  • Supports exact domain matches (e.g., https://example.com)
  • Supports wildcard subdomains (e.g., https://*.example.com)
  • Prevents dangerous patterns (wildcard-only, multiple wildcards, TLD wildcards)
  • Handles port numbers correctly

Comprehensive Validation

  • All origins must be valid URLs
  • Configuration is validated on startup
  • Error messages are clear and actionable
  • Graceful fallbacks for invalid environment variable values

Environment Configuration

Required Environment Variables

# Production example
NODE_ENV=production
CORS_ALLOWED_ORIGINS=https://app.chronopay.com,https://*.chronopay.com
CORS_ALLOW_CREDENTIALS=true
CORS_MAX_AGE=86400

# Development example (uses defaults, no env vars needed)
NODE_ENV=development

Testing & Validation

Test Results

Test Suites: 3 passed, 3 total
Tests:       58 passed, 58 total
Coverage:    > 95% for all touched modules

What's Tested

  1. ✅ All origin validation edge cases
  2. ✅ Environment variable parsing
  3. ✅ Configuration validation
  4. ✅ Wildcard pattern matching
  5. ✅ Preflight request handling
  6. ✅ CORS header generation
  7. ✅ Security constraint enforcement
  8. ✅ Credential handling
  9. ✅ Error cases and failure modes

Files Changed

New Files (3)

  • src/config/cors.ts - Configuration and validation logic
  • src/middleware/cors.ts - CORS middleware implementation
  • docs/CORS_CONFIGURATION.md - Comprehensive documentation

Modified Files (4)

  • src/index.ts - Integrated CORS middleware
  • jest.config.cjs - Updated TypeScript configuration
  • src/__tests__/validation.test.ts - Fixed ESM imports
  • package.json - Added swagger dependencies

Total Lines of Code

  • Implementation: ~400 lines (cors.ts + middleware, including comments)
  • Tests: ~550 lines (52 comprehensive tests)
  • Documentation: ~300 lines

Security Considerations

Assumptions Made

  1. Origin header is trustworthy (browsers only send it for CORS requests)
  2. HTTPS is used in production (no http:// in production origins)
  3. Credential isolation is maintained through specific origin setting (not wildcard)

Failure Modes Handled

  1. Empty allowlist: Clear warning logged, no origins allowed
  2. Invalid origin: Rejected with validation error, helpful message
  3. Pattern mismatch: Origin not matched silently (origin not added to response)
  4. Configuration error: Server fails to start with error details

Rollout Checklist

  • Feature implemented with comprehensive tests
  • Code coverage > 95% for changed modules
  • All tests passing (58 tests)
  • TypeScript compilation successful
  • Documentation complete
  • Security assumptions validated
  • Edge cases tested
  • No breaking changes to existing API
  • Backward compatible (app still works with configuration)

Next Steps for Deployment

  1. Set CORS_ALLOWED_ORIGINS environment variable for your deployment
  2. Run tests to verify: npm test
  3. Build project: npm run build
  4. Start server: npm start
  5. Verify CORS headers in browser network inspector

Related Issues

  • closes #45 [BE-045] Implement CORS Allowlist Configuration

Commit Message Template

feat(cors): implement allowlist configuration (BE-045)

- Add CORS configuration module with environment-based settings
- Create CORS middleware for origin validation
- Support wildcard patterns for flexible subdomain matching  
- Replace permissive default cors() with secure allowlist validation
- Include 98.68% statement coverage with comprehensive tests
- Add complete documentation and inline comments