Files

6.3 KiB

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:

'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

'cors' => [
    'enabled' => true,
    'allowed_origins' => [
        'http://localhost:3000',
        'http://localhost:8080',
        'http://127.0.0.1:3000',
    ],
    'allow_credentials' => false,
    'max_age' => 3600,
],

Production

'cors' => [
    'enabled' => true,
    'allowed_origins' => [
        'https://app.example.com',
        'https://admin.example.com',
    ],
    'allow_credentials' => false,
    'max_age' => 86400,
],
'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

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

$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