Implements FED-010: Agent Spawn via Federation feature that enables spawning and managing Claude agents on remote federated Mosaic Stack instances via COMMAND message type. Features: - Federation agent command types (spawn, status, kill) - FederationAgentService for handling agent operations - Integration with orchestrator's agent spawner/lifecycle services - API endpoints for spawning, querying status, and killing agents - Full command routing through federation COMMAND infrastructure - Comprehensive test coverage (12/12 tests passing) Architecture: - Hub → Spoke: Spawn agents on remote instances - Command flow: FederationController → FederationAgentService → CommandService → Remote Orchestrator - Response handling: Remote orchestrator returns agent status/results - Security: Connection validation, signature verification Files created: - apps/api/src/federation/types/federation-agent.types.ts - apps/api/src/federation/federation-agent.service.ts - apps/api/src/federation/federation-agent.service.spec.ts Files modified: - apps/api/src/federation/command.service.ts (agent command routing) - apps/api/src/federation/federation.controller.ts (agent endpoints) - apps/api/src/federation/federation.module.ts (service registration) - apps/orchestrator/src/api/agents/agents.controller.ts (status endpoint) - apps/orchestrator/src/api/agents/agents.module.ts (lifecycle integration) Testing: - 12/12 tests passing for FederationAgentService - All command service tests passing - TypeScript compilation successful - Linting passed Refs #93 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
Issue #192: Fix CORS Configuration for Cookie-Based Authentication
Objective
Fix CORS configuration in the API to properly support cookie-based authentication with credentials across origins.
Problem
Current CORS settings are blocking cookie-based authentication flow. Likely issues:
- Credentials not enabled
- Wildcard origin with credentials (invalid combination)
- Incorrect cookie SameSite settings
- Missing Access-Control-Allow-Credentials header
Approach
-
Investigation Phase
- Read current CORS configuration in main.ts and app.module.ts
- Check authentication module CORS settings
- Identify specific blocking issues
-
TDD Phase (Red-Green-Refactor)
- Write tests for cookie-based auth across origins
- Write tests for CORS headers with credentials
- Verify tests fail with current configuration
-
Implementation Phase
- Fix CORS configuration to enable credentials
- Configure proper origin handling (no wildcard with credentials)
- Set appropriate cookie SameSite settings
- Ensure Access-Control-Allow-Credentials header
-
Verification Phase
- Run all tests (target >85% coverage)
- Verify cookie-based auth works
- Security review
Progress
- Create scratchpad
- Read current CORS configuration
- Read authentication module setup
- Write tests for cookie-based auth (PASSED)
- Implement CORS fixes in main.ts
- Verify all tests pass (CORS tests: PASS, Auth tests: PASS)
- Security review (see below)
- Commit changes
- Update issue #192
Findings
Current Configuration (main.ts:44)
app.enableCors();
Problem: Uses default CORS settings with no credentials support.
Better-Auth Configuration (auth.config.ts:31-36)
trustedOrigins: [
process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000",
"http://localhost:3001", // API origin (dev)
"https://app.mosaicstack.dev", // Production web
"https://api.mosaicstack.dev", // Production API
];
Good! Better-Auth already has trusted origins configured.
Testing
Test Scenarios
- OPTIONS preflight with credentials
- Cookie transmission in cross-origin requests
- Access-Control-Allow-Credentials header presence
- Origin validation (not wildcard)
- Cookie SameSite settings
Security Considerations
- No wildcard origins with credentials (security violation)
- Proper origin whitelist validation
- Secure cookie settings (HttpOnly, Secure, SameSite)
- CSRF protection considerations
Security Review
CORS Configuration Changes ✓ APPROVED
File: apps/api/src/main.ts
Security Measures Implemented
-
Origin Whitelist - Specific allowed origins, no wildcard
http://localhost:3000(dev frontend)http://localhost:3001(dev API)https://app.mosaicstack.dev(prod frontend)https://api.mosaicstack.dev(prod API)- Dynamic origin from
NEXT_PUBLIC_APP_URLenv var
-
Credentials Support -
credentials: true- Required for cookie-based authentication
- Properly paired with specific origins (NOT wildcard)
-
Origin Validation Function
- Exact string matching (no regex vulnerabilities)
- Rejects untrusted origins with error
- Allows requests with no origin (mobile apps, Postman)
-
Security Headers
Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: <specific-origin>Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONSAccess-Control-Allow-Headers: Content-Type, Authorization, CookieAccess-Control-Expose-Headers: Set-CookieAccess-Control-Max-Age: 86400(24h preflight cache)
Attack Surface Analysis
- ✅ No CORS bypass vulnerabilities - Exact origin matching
- ✅ No wildcard + credentials - Security violation prevented
- ✅ No subdomain wildcards - Prevents subdomain takeover attacks
- ✅ Cookie security - Properly exposed Set-Cookie header
- ✅ Preflight caching - 24h cache reduces preflight overhead
Compliance
- ✅ OWASP CORS Best Practices
- ✅ MDN Web Security Guidelines
- ✅ Better-Auth Integration - Aligns with
trustedOriginsconfig
Environment Variables
Added NEXT_PUBLIC_APP_URL to:
.env.example(template).env(local development)
Notes
CRITICAL: This blocks the entire authentication flow.
Implementation Summary
Fixed CORS configuration to enable cookie-based authentication by:
- Adding explicit origin whitelist function
- Enabling
credentials: true - Configuring proper security headers
- Adding environment variable support
CORS + Credentials Rules
credentials: truerequired for cookies- Cannot use
origin: '*'with credentials - Must specify exact origins or use dynamic validation
- Must set
Access-Control-Allow-Credentials: trueheader - Cookies must have appropriate SameSite setting
Cookie Settings for Cross-Origin
HttpOnly: true- Prevent XSSSecure: true- HTTPS only (production)SameSite: 'lax'or'none'- Cross-origin supportSameSite: 'none'requiresSecure: true