# CORS Management Documentation ## Overview This API now includes comprehensive CORS (Cross-Origin Resource Sharing) management. CORS allows your API to be accessed from web applications hosted on different domains. ## How It Works ### Automatic CORS Header Application All API responses automatically include CORS headers when CORS is enabled. This allows web applications from configured origins to access your API. ### Preflight Request Handling The API automatically handles preflight OPTIONS requests (sent by browsers before actual requests to CORS-protected resources). These are handled with a 204 No Content response. ### Origin Validation Only requests from configured allowed origins are accepted. Requests from unauthorized origins are rejected. ## Configuration Edit `config/config.php` to configure CORS: ```php 'cors' => [ 'enabled' => true, // Enable/disable CORS 'allowed_origins' => [ 'http://localhost:3000', 'https://example.com', ], 'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], 'allowed_headers' => ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept'], 'exposed_headers' => ['Content-Length', 'X-JSON-Response-Code'], 'allow_credentials' => false, 'max_age' => 86400, ], ``` ## Configuration Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `enabled` | bool | `true` | Enable or disable CORS | | `allowed_origins` | array | `[]` | List of domains allowed to access the API. Use `'*'` to allow all (NOT recommended) | | `allowed_methods` | array | `GET, POST, PUT, DELETE, PATCH, OPTIONS` | HTTP methods allowed | | `allowed_headers` | array | `Content-Type, Authorization, X-Requested-With, Accept` | Headers allowed in requests | | `exposed_headers` | array | `Content-Length, X-JSON-Response-Code` | Headers exposed to the client | | `allow_credentials` | bool | `false` | Allow credentials (cookies, auth) in requests | | `max_age` | int | `86400` | Browser cache time for preflight (seconds) | ## Setup for Different Environments ### Development ```php 'cors' => [ 'enabled' => true, 'allowed_origins' => [ 'http://localhost:3000', 'http://localhost:8080', 'http://127.0.0.1:3000', ], 'allow_credentials' => false, 'max_age' => 3600, ], ``` ### Production ```php 'cors' => [ 'enabled' => true, 'allowed_origins' => [ 'https://app.example.com', 'https://admin.example.com', ], 'allow_credentials' => false, 'max_age' => 86400, ], ``` ### Allow All Origins (NOT RECOMMENDED for Production) ```php 'cors' => [ 'enabled' => true, 'allowed_origins' => ['*'], 'allow_credentials' => false, ], ``` ## Browser Preflight Requests When making cross-origin requests with certain headers or methods (like PUT or DELETE), browsers automatically send a preflight OPTIONS request. The API handles these automatically: ``` Browser sends: OPTIONS /api/resource API responds: 204 No Content + CORS headers Browser sees: Request is allowed, proceeds with actual request ``` ## Testing CORS ### Using curl ```bash # Test CORS with curl curl -H "Origin: http://localhost:3000" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type" \ -X OPTIONS \ http://localhost:8000/api/users/index -v ``` ### Expected Response Headers ``` HTTP/1.1 204 No Content Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, Accept Access-Control-Max-Age: 86400 ``` ## Security Considerations 1. **Be Specific with Origins**: Always specify exact allowed origins. Don't use `'*'` in production unless absolutely necessary. 2. **Credentials**: Only set `allow_credentials: true` if you understand the security implications. This allows cross-origin requests to send cookies. 3. **Sensitive Headers**: Don't expose sensitive headers in `exposed_headers`. Only expose what clients actually need. 4. **HTTPS in Production**: Always use HTTPS in production to prevent man-in-the-middle attacks. ## CorsManager Class The `CorsManager` class handles all CORS logic. You can also use it programmatically: ```php $corsManager = $container->make(\Api\Core\CorsManager::class); // Check if current request is allowed if ($corsManager->isOriginAllowed()) { // Process request } // Apply CORS headers manually $corsManager->applyHeaders(); // Check for preflight request if ($corsManager->isPreflightRequest()) { $corsManager->handlePreflight(); } ``` ## Troubleshooting ### Preflight request fails - Check that the origin in the request matches one in `allowed_origins` - Verify CORS is enabled in config - Check browser console for CORS error messages ### Missing CORS headers in response - Ensure CORS is enabled: `'enabled' => true` - Verify the requesting origin is in `allowed_origins` - Check that `CorsManager` is properly initialized in the container ### "No Access-Control-Allow-Origin header" - Browser origin is not in `allowed_origins` - Add the origin or use `'*'` (only for development) ## References - [MDN: CORS Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) - [OWASP: CORS](https://owasp.org/www-community/CORS)