Update - June 16, 2025: This post has been updated to better explain CORS as a security feature rather than a problem to be “fixed.” The content is now language-agnostic and emphasizes why CORS is essential for web security.

Ahnii!

CORS (Cross-Origin Resource Sharing) is a crucial web security mechanism that controls how web pages from one domain can access resources from another domain. Rather than being a problem to solve, CORS is actually a security feature that protects users while enabling legitimate cross-origin communication.

CORS Diagram

Why CORS Exists

Browsers enforce the same-origin policy by default, which prevents scripts from one origin from accessing resources on another origin. This security measure protects users from malicious websites that might try to access sensitive data from other sites you’re logged into.

Without CORS, a malicious website could potentially:

  • Read your emails from Gmail if you’re logged in
  • Access your banking information from another tab
  • Make unauthorized requests on your behalf

CORS provides a controlled way for servers to explicitly permit cross-origin requests while maintaining security. Learn more about CORS on MDN.

Understanding Origins

An origin consists of three parts: protocol, host, and port. These are considered different origins:

  • http://localhost:3000 and http://localhost:8080 (different ports)
  • https://api.example.com and http://api.example.com (different protocols)
  • https://app.example.com and https://api.example.com (different subdomains)

Implementing CORS

When you need to allow cross-origin requests, you configure CORS headers on your server. Here’s a basic implementation:

// Node.js/Express example
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', 'https://yourdomain.com');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    next();
});
# Python/Flask example
from flask_cors import CORS

app = Flask(__name__)
CORS(app, origins=['https://yourdomain.com'])
// Java/Spring example
@CrossOrigin(origins = "https://yourdomain.com")
@RestController
public class ApiController {
    // Your endpoints here
}

Security Best Practices

Never use wildcards in production:

// DON'T do this in production
res.header('Access-Control-Allow-Origin', '*');

// DO this instead
res.header('Access-Control-Allow-Origin', 'https://yourdomain.com');

Be specific with allowed methods and headers:

res.header('Access-Control-Allow-Methods', 'GET, POST'); // Only what you need
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');

Consider credentials carefully:

// Only if you need to send cookies/auth headers
res.header('Access-Control-Allow-Credentials', 'true');

Handling Preflight Requests

For complex requests (those with custom headers, or using methods other than GET/POST), browsers send a preflight OPTIONS request first. Your server needs to handle these:

// Handle preflight requests
app.options('*', (req, res) => {
    res.header('Access-Control-Allow-Origin', 'https://yourdomain.com');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.sendStatus(200);
});

Production Recommendations

Use established CORS libraries rather than implementing manually:

Node.js:

const cors = require('cors');
app.use(cors({
    origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
    credentials: true
}));

Python:

from flask_cors import CORS
CORS(app, origins=['https://yourdomain.com'])

PHP:

// Use a CORS middleware or library like neomerx/cors-psr7

Key Takeaways

CORS is not a barrier to overcome but a security feature that enables safe cross-origin communication. When implementing CORS:

  1. Understand the why: CORS protects users from malicious cross-origin requests
  2. Be restrictive: Only allow the origins, methods, and headers you actually need
  3. Use libraries: Leverage well-tested CORS implementations rather than rolling your own
  4. Test thoroughly: Verify your CORS configuration works with your frontend applications
  5. Monitor: Keep track of CORS errors in production to catch configuration issues

Remember, CORS headers are set on the server side, not the client. The server decides which cross-origin requests to allow, giving you full control over your API’s security posture.

Additional Resources:

Got questions about CORS implementation? Drop a comment below!

Baamaapii 👋