The Ultimate CORS Policies Cheat Sheet: A Complete Guide for Web Developers

Introduction to CORS

Cross-Origin Resource Sharing (CORS) is a security mechanism built into modern browsers that controls how web pages in one domain can request resources from another domain. CORS extends and adds flexibility to the Same-Origin Policy (SOP), which otherwise prevents websites from making cross-origin HTTP requests. Understanding CORS is essential for developing secure web applications, especially when building APIs or frontend applications that interact with third-party services.

Core CORS Concepts

Same-Origin Policy (SOP)

  • Definition: Security feature restricting web pages from making requests to domains different from their origin
  • Origin components: Protocol (http/https), domain, and port
  • Example: A page from https://example.com cannot make requests to https://api.com without CORS

CORS Headers

HeaderPurposeExample
Access-Control-Allow-OriginSpecifies which origins can access the resourceAccess-Control-Allow-Origin: https://example.com
Access-Control-Allow-MethodsSpecifies allowed HTTP methodsAccess-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-HeadersSpecifies allowed request headersAccess-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-CredentialsIndicates if requests can include credentialsAccess-Control-Allow-Credentials: true
Access-Control-Expose-HeadersHeaders that browsers are allowed to accessAccess-Control-Expose-Headers: X-Custom-Header
Access-Control-Max-AgeDuration preflight results can be cachedAccess-Control-Max-Age: 3600

Request Types

Simple Requests

  • Don’t trigger preflight checks
  • Must use GET, HEAD, or POST methods
  • Only allowed headers: Accept, Accept-Language, Content-Language, Content-Type
  • Content-Type limited to: application/x-www-form-urlencoded, multipart/form-data, or text/plain

Preflighted Requests

  • Require an OPTIONS request before the actual request
  • Triggered by: custom headers, non-simple methods (PUT, DELETE), or complex Content-Types (JSON)
  • Server must respond to OPTIONS with appropriate CORS headers

Credentialed Requests

  • Include cookies or HTTP authentication
  • Require withCredentials: true in request configuration
  • Server must respond with Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin cannot be wildcard (*), must specify exact origin

CORS Implementation Process

Server-Side Implementation

  1. Simple Server Configuration:

    • Add appropriate CORS headers to all responses
    • Set Access-Control-Allow-Origin to allowed origins
  2. Handling Preflight Requests:

    • Listen for OPTIONS requests
    • Respond with CORS headers but no body content
    • Return 200/204 status code
  3. Credential Handling:

    • When supporting credentials, set Access-Control-Allow-Credentials: true
    • Specify exact origin in Access-Control-Allow-Origin

Client-Side Implementation

  1. Making Simple Cross-Origin Requests:

    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => console.log(data));
    
  2. Making Credentialed Requests:

    fetch('https://api.example.com/data', {
      credentials: 'include'
    })
      .then(response => response.json())
      .then(data => console.log(data));
    
  3. Using XMLHttpRequest with CORS:

    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://api.example.com/data');
    xhr.withCredentials = true; // For credentialed requests
    xhr.send();
    

Framework-Specific CORS Configuration

Express.js (Node.js)

// Simple CORS middleware
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://example.com');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  if (req.method === 'OPTIONS') {
    return res.status(204).send('');
  }
  next();
});

// Or use the cors package
const cors = require('cors');
app.use(cors({
  origin: 'https://example.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

Spring Boot (Java)

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("https://example.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("Content-Type", "Authorization")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

Django (Python)

# settings.py
INSTALLED_APPS = [
    # ...
    'corsheaders',
    # ...
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    # ... other middleware
]

CORS_ALLOWED_ORIGINS = [
    "https://example.com",
]

CORS_ALLOW_METHODS = [
    "GET",
    "POST",
    "PUT",
    "DELETE",
    "OPTIONS",
]

CORS_ALLOW_HEADERS = [
    "Content-Type",
    "Authorization",
]

CORS_ALLOW_CREDENTIALS = True

Common CORS Errors and Solutions

ErrorDescriptionSolution
“Cross-Origin Request Blocked”Browser blocked request due to CORS policyAdd proper CORS headers on server
“Origin not allowed”Request origin not in allowed listAdd origin to Access-Control-Allow-Origin
“Method not allowed”HTTP method not permittedAdd method to Access-Control-Allow-Methods
“Request header not allowed”Header not in allowed listAdd header to Access-Control-Allow-Headers
“Credentials not supported”Using credentials with wildcard originSpecify exact origin instead of *
“Preflight response invalid”OPTIONS response missing required headersEnsure proper CORS headers in preflight response

CORS Security Best Practices

  • Avoid wildcard origins: Use specific domains in Access-Control-Allow-Origin instead of *
  • Limit allowed methods: Only specify HTTP methods your API actually supports
  • Restrict allowed headers: Only allow headers your application needs
  • Set reasonable max-age: Balance between performance and security updates
  • Validate Origin header: Implement server-side validation of the Origin header
  • Use HTTPS: Always use HTTPS for cross-origin requests to prevent man-in-the-middle attacks
  • Apply rate limiting: Protect your API from abuse with rate limiting
  • Implement token-based auth: Use tokens instead of cookies when possible

Debugging CORS Issues

  1. Check browser console: Look for specific CORS error messages
  2. Verify server responses: Use network tab to see if proper headers are being returned
  3. Test with curl: Bypass browser restrictions to isolate server issues
    curl -X OPTIONS https://api.example.com/data -H "Origin: https://example.com" -v
    
  4. Use Chrome CORS extension: Temporarily disable CORS for testing (never in production)
  5. Check for proxy issues: Verify if intermediate proxies strip CORS headers

Resources for Further Learning

Tools for CORS Testing and Implementation

Remember that CORS is a security feature, not a bug! Proper implementation protects both your users and your services.

Scroll to Top