Skip to content
IRC-CodingIRC-Coding
CORSCross-Origin Resource SharingAPI SecurityPreflightOrigin HeaderWeb Security

CORS for APIs: Secure Cross-Origin Request Handling

Master CORS for APIs: origins, preflight requests, allowed headers and methods, security risks, and best practices for proper configuration.

S

schutzgeist

5 min read
CORS for APIs: Secure Cross-Origin Request Handling

CORS for APIs

CORS enables controlled access to resources across domain boundaries, but must be configured correctly to avoid security risks.

Quick Overview

CORS stands for Cross-Origin Resource Sharing—a browser mechanism that allows requests for resources from a different domain than the one serving the current webpage. By default, browsers block cross-origin requests to prevent unauthorized data access. CORS lets servers explicitly specify which origins, methods, and headers are permitted. Proper configuration is essential for APIs consumed by browser-based applications, yet overly permissive settings create security vulnerabilities that attackers can exploit. Key concepts include the Origin header, preflight requests, Access-Control headers, and the distinction between simple and complex requests.

Core Concepts

Same-Origin Policy

The Same-Origin Policy is a fundamental browser security mechanism that prevents a webpage from accessing data belonging to another domain. Origin is determined by protocol, domain, and port. Different subdomains or ports are treated as different origins.

Origin Header

The browser includes an Origin header when making cross-origin requests, specifying the source domain. The server uses this header to decide whether to allow the request and responds with Access-Control-Allow-Origin and other CORS headers.

Access-Control-Allow-Origin

This header specifies which origins may access the resource. It can name a specific domain like https://app.example.com or use * to allow all domains. Wildcards should be avoided for APIs with authentication or sensitive data.

Access-Control-Allow-Methods

This header lists the HTTP methods permitted for cross-origin requests, such as GET, POST, PUT, and DELETE. Only explicitly allowed methods may be used by the browser.

Access-Control-Allow-Headers

This header indicates which additional headers the client may include in its request. Standard headers like Content-Type, Accept, or Authorization must sometimes be explicitly allowed if they’re custom.

Access-Control-Allow-Credentials

This header permits cookies, HTTP authentication, or client certificates to be sent with cross-origin requests. When set to true, Access-Control-Allow-Origin cannot be * but must specify a concrete domain.

Preflight Request

For complex cross-origin requests, the browser first sends an OPTIONS request—a preflight check. The server responds with allowed methods, headers, and origins. Only after this exchange does the browser send the actual request. Preflight requests are triggered for methods like PUT, DELETE, or custom headers.

Simple and Complex Requests

Simple requests use GET, HEAD, or POST with specific content types and standard headers; they skip preflight. Complex requests use other methods, custom headers, or non-standard content types and trigger a preflight check.

CORS and Security Risks

Misconfigured CORS can lead to unauthorized access. Particularly dangerous are Access-Control-Allow-Origin: * paired with credentials, dynamically mirroring the Origin header without validation, and permitting unsafe methods. Attackers can exploit these oversights to steal data in the browser.

CORS in API Configuration

CORS is typically configured at the API gateway, web server, or application layer. Node.js commonly uses the cors middleware package; Spring Boot offers @CrossOrigin; ASP.NET Core has UseCors. Whatever the technology, configuration should be restrictive and explicit.

Debugging CORS

CORS errors in the browser often lack detail. Browser developer tools and network logs help inspect preflight and main requests. Server-side logging should record Origin headers and responses.

Practical Example

A web application at https://app.example.com calls an API at https://api.example.com. The API must allow CORS for that origin.

The browser sends the request:

GET /api/v1/profile
Host: api.example.com
Origin: https://app.example.com
Authorization: Bearer TOKEN

The server responds with CORS headers:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

{
  "name": "Max Mustermann",
  "email": "max@example.com"
}

For a PUT request, the browser first sends a preflight:

OPTIONS /api/v1/profile
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

The server responds to the preflight:

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

Only then does the browser send the actual PUT request. This ensures that only authorized origins can access the API.

FAQ: CORS for APIs

1. What is CORS?

CORS stands for Cross-Origin Resource Sharing. It is a browser mechanism that allows servers to specify which other domains may access their resources.

2. What is the Same-Origin Policy?

The Same-Origin Policy restricts webpages to accessing resources from the same domain only. It protects against unauthorized data access between different websites.

3. What is a Preflight Request?

A preflight request is an OPTIONS request that the browser sends before complex cross-origin requests. The server responds with the allowed origins, methods, and headers.

4. What is Access-Control-Allow-Origin?

Access-Control-Allow-Origin specifies which origins may access a resource. It can name a specific domain or use a wildcard. Wildcards should be avoided when credentials are involved.

5. What is Access-Control-Allow-Credentials?

Access-Control-Allow-Credentials permits cookies, HTTP authentication, or client certificates to be sent with cross-origin requests. When true, the Origin header cannot be * but must specify a concrete domain.

6. What is the Origin Header?

The Origin header is sent by the browser with cross-origin requests. It contains the source domain and helps the server decide whether to allow the request.

7. Which requests trigger a preflight?

Complex requests using methods like PUT, DELETE, or PATCH, custom headers, or non-standard content types trigger a preflight. Simple GET, HEAD, and POST requests usually do not.

8. Why is Access-Control-Allow-Origin: * dangerous?

A wildcard allows any origin to access the resource. For APIs with credentials or sensitive data, this enables unauthorized access. A whitelist of specific allowed domains is safer.

9. What is Access-Control-Allow-Methods?

Access-Control-Allow-Methods lists the HTTP methods permitted for cross-origin requests, such as GET, POST, PUT, and DELETE.

10. What is Access-Control-Allow-Headers?

Access-Control-Allow-Headers indicates which additional headers the client may include in a cross-origin request. Custom headers like Authorization often must be explicitly allowed.

11. Can CORS prevent server attacks?

No, CORS is a browser mechanism, not server protection. Authentication, authorization, and input validation must still be enforced on the server side.

12. What is Access-Control-Max-Age?

Access-Control-Max-Age specifies how long the browser may cache a preflight response. This reduces repeated OPTIONS requests.

13. Why does CORS work in Postman but not in the browser?

Postman and similar tools do not enforce CORS because they lack a Same-Origin Policy. CORS is a browser-specific security mechanism.

14. What is dynamic Origin mirroring?

Dynamic Origin mirroring occurs when a server simply echoes back the client’s Origin header. This is unsafe because it allows any origin—equivalent to using a wildcard.

15. How do you test CORS properly?

Test CORS directly in the browser using different origins. Browser developer tools show preflight and main requests. Also verify that credentials are not combined with wildcards and that origin validation works correctly.

References

  1. https://developer.mozilla.org/docs/Web/HTTP/CORS
  2. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/07-Testing_Cross_Origin_Resource_Sharing
  3. https://fetch.spec.whatwg.org/#cors-protocol

To dive deeper into CORS, web security, and API security, check out these books:

IT CyberSecurity

Books about IT security, authentication, encryption and security best practices

The Web Application Hacker's Handbook von Dafydd Stuttard, Marcus Pinto

The Web Application Hacker's Handbook von Dafydd Stuttard, Marcus Pinto

Bei Amazon ansehen

Affiliate-Link: Bei einem Kauf erhalten wir möglicherweise eine Provision.

Back to Blog
Share:

Related Posts