Introduction to CORS
Cross-Origin Resource Sharing (CORS) is a security mechanism built into browsers that restricts web pages from making requests to a different domain than the one that served the original page. CORS headers enable servers to specify which origins are permitted to access their resources, enhancing security while allowing legitimate cross-origin communication.
Core CORS Concepts
- Same-Origin Policy: By default, web browsers restrict web pages from making requests to a different domain than the one that served the web page.
- Cross-Origin Request: Any request made from one origin (domain, protocol, or port) to a different origin.
- Preflight Request: An automatic OPTIONS request sent by browsers before the actual request to check if the CORS protocol is understood.
- Simple Requests: Requests that don’t trigger a preflight (specific methods and headers only).
Essential CORS Headers
Header | Purpose | Example Value |
---|---|---|
Access-Control-Allow-Origin | Specifies which origins can access the resource | https://example.com or * (all origins) |
Access-Control-Allow-Methods | Specifies the HTTP methods allowed | GET, POST, PUT, DELETE, OPTIONS |
Access-Control-Allow-Headers | Specifies which headers can be used | Content-Type, Authorization |
Access-Control-Allow-Credentials | Controls if credentials can be included in request | true (cannot be used with * origin) |
Access-Control-Max-Age | Duration to cache preflight results (seconds) | 3600 (1 hour) |
Access-Control-Expose-Headers | Headers accessible to JavaScript | Content-Length, X-Custom-Header |
Implementing CORS: Step-by-Step
Identify requirements:
- Determine which origins need access
- Identify required HTTP methods
- Decide if credentials should be allowed
Set up the server response headers:
- Configure basic headers for all responses
- Set up preflight response for OPTIONS requests
Test cross-origin requests:
- Verify simple requests work
- Verify preflight requests resolve correctly
- Test with actual client applications
Monitor and adjust:
- Check for CORS errors in browser console
- Refine headers as needed
Common CORS Scenarios
Public API (No Credentials)
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Max-Age: 3600
Restricted API with Authentication
Access-Control-Allow-Origin: https://trusted-client.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
Multiple Allowed Origins
// Set dynamically based on the Origin header
if (allowedOrigins.includes(requestOrigin)) {
response.setHeader('Access-Control-Allow-Origin', requestOrigin);
}
Common CORS Challenges and Solutions
Challenge | Solution |
---|---|
“No ‘Access-Control-Allow-Origin’ header is present” | Add the correct origin to server response headers |
“Method not allowed by Access-Control-Allow-Methods” | Include the required HTTP method in the Allow-Methods header |
“Request header field not allowed” | Add the custom header to Access-Control-Allow-Headers |
“Credentials flag is true, but Access-Control-Allow-Origin is not specific origin” | Replace * with specific origin when using credentials |
CORS errors in production but not development | Ensure production environment has matching CORS configuration |
CORS Implementation by Framework
Framework | Implementation |
---|---|
Express.js | Use cors middleware: app.use(cors({origin: 'https://example.com', methods: ['GET', 'POST']})) |
Django | Use django-cors-headers package and add to MIDDLEWARE setting |
Spring Boot | Use @CrossOrigin annotation or configure CorsRegistry |
ASP.NET | Configure CORS policy in Startup.cs using services.AddCors() |
Flask | Use Flask-CORS extension: CORS(app, resources={r"/api/*": {"origins": "*"}}) |
Best Practices
- Be specific with origins: Avoid
*
whenever possible, especially with credentials - Limit exposed methods: Only include HTTP methods your API actually needs
- Set reasonable max-age: Balance between performance and flexibility to change
- Test thoroughly: Use browser developer tools to verify CORS is working correctly
- Secure implementation: Don’t use CORS as your only security measure
- Use proper error handling: Return meaningful error messages for CORS issues
- Consider environment differences: Ensure consistency between development and production
Troubleshooting CORS Issues
- Check the browser console for specific CORS error messages
- Verify network requests using browser developer tools
- Confirm server configuration is correctly implementing CORS headers
- Use CORS debugging tools like “CORS Unblock” extension during development
- Test with curl to isolate browser vs. server issues