What Is CORS
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that controls how web pages can request resources from another domain (origin). An origin is a combination of protocol, domain, and port.
By default, browsers block cross-origin requests for security reasons; this is called the Same-Origin Policy. CORS allows a server to explicitly permit requests from specific origins.
Example of a cross-origin request: a frontend on https://app.example.com makes a request to an API on https://api.example.com. The browser will block it unless CORS is configured.
Why CORS Is Needed
API security: CORS limits the list of domains that can make requests to your API.
CSRF protection: Proper CORS configuration helps prevent request forgery attacks.
Mobile apps and SPAs: Single Page Applications on a separate domain require CORS.
Microservice architecture: Communication between services through a browser requires CORS.
How CORS Works
Simple Requests
GET and POST with Content-Type: application/x-www-form-urlencoded — the browser adds the Origin header and checks the response.
Preflight Request
For complex requests (PUT, DELETE, custom headers), the browser first sends a OPTIONS request:
OPTIONS /api/users HTTP/1.1
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
The server must respond:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Main CORS Headers
Server Response Headers
Access-Control-Allow-Origin — permitted origins:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods — permitted HTTP methods:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers — permitted request headers:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
Access-Control-Allow-Credentials — allow cookies to be sent:
Access-Control-Allow-Credentials: true
Access-Control-Max-Age — preflight response caching (seconds):
Access-Control-Max-Age: 86400
Configuring CORS in Next.js
// next.config.js
async headers() {
return [{
source: '/api/:path*',
headers: [{
key: 'Access-Control-Allow-Origin',
value: 'https://app.example.com'
}]
}]
}Configuring CORS in Nginx
location /api/ {
add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
if ($request_method = 'OPTIONS') {
return 204;
}
}Check CORS on reChecker
Use Security Headers to check your CORS configuration. The tool will show:
- The presence and value of Access-Control-Allow-Origin
- The potentially dangerous wildcard (*)
- Other security headers
- Recommendations for improvement
FAQ
Is a wildcard (*) in CORS dangerous? Yes, for APIs with authentication. A wildcard allows requests from any domain. If the API uses cookies for authentication, a wildcard combined with Allow-Credentials creates a CSRF vulnerability. Always specify particular domains.
How do I debug CORS errors in a browser? Open DevTools → the Network tab → find the blocked request. The Console will show a detailed error message. Check that the server returns the correct Access-Control-Allow-* headers.
Should CORS be configured on the server or in the code? It is better to configure it at the server level (Nginx/Apache) for consistency. However, configuring it in the application code is also acceptable, especially if CORS rules are complex or depend on the request path.