CORS
Set up cross-origin access for public APIs or authenticated frontends with support for multiple origins and dynamic closures.
Kirby Native CORS Support
Starting with Kirby 5.2.0, CORS is built into Kirby core. Configure it directly in your config.php:
Minimal Setup (Public API)
Enable CORS with sensible defaults:
config.php
return [
'cors' => true
];
This applies defaults that work for most public APIs: wildcard origin (*), standard HTTP methods, and no credentials.
Headless CMS With Authentication
For headless setups with bearer token authentication:
config.php
return [
'cors' => [
'allowOrigin' => 'https://example.com',
'allowMethods' => ['GET', 'POST', 'PATCH', 'DELETE'],
'allowHeaders' => true,
'allowCredentials' => true
]
];
Setting
allowCredentials to true lets browsers include cookies and HTTP authentication with cross-origin requests. Only enable this when the requesting origin is fully trusted and under your control.Multiple Frontend Apps
Allow multiple origins with specific configuration:
config.php
return [
'cors' => [
'allowOrigin' => [
'https://app.example.com',
'https://admin.example.com'
],
'allowHeaders' => [
'Authorization',
'Content-Type',
'X-Language',
'X-Cacheable'
],
'allowCredentials' => true
]
];
Dynamic CORS Configuration
For request-based CORS configuration, use a closure:
config.php
return [
'cors' => function ($kirby) {
$origin = $kirby->request()->header('Origin');
// Allow specific origins with credentials
if (in_array($origin, ['https://app1.com', 'https://app2.com'])) {
return [
'allowOrigin' => $origin,
'allowCredentials' => true,
'allowMethods' => ['GET', 'POST']
];
}
// Fallback to wildcard for other origins
return ['allowOrigin' => '*'];
}
];
Available Options
| Option | Type | Default | Description |
|---|---|---|---|
allowOrigin | string|array | '*' | Allowed origins (e.g., '*', 'https://example.com', or array for multiple origins) |
allowMethods | string|array | ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'] | Allowed HTTP methods |
allowHeaders | string|array|bool | [] | Allowed request headers. true reflects client headers; array allowlists specific headers |
maxAge | int | null | Preflight cache duration in seconds |
allowCredentials | bool | false | Allow requests with credentials (cookies, auth) |
exposeHeaders | string|array | [] | Response headers exposed to the browser |
Security Considerations
Every origin you allow can read your API from a visitor's browser – keep origins, methods, and headers down to what your frontend needs, and reach for the wildcard only on an API that is public anyway.