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

CORS for APIs: Secure Cross-Origin Request Handling

Master CORS: origins, preflight requests, headers, methods, security risks and best practices for proper API 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. It’s a mechanism that allows browsers to request resources from a different domain than the one that served the current webpage. By default, browsers block such cross-origin requests to protect against unauthorized data access. CORS lets servers explicitly specify which origins, methods, and headers are permitted. Proper CORS configuration matters for APIs used by browser-based applications. At the same time, an overly permissive configuration creates a security vulnerability by enabling cross-origin attacks. Key concepts include the Origin header, preflight requests, Access-Control headers, and the distinction between simple and complex requests.

Key Components

Same-Origin Policy

The Same-Origin Policy is a fundamental browser security mechanism. It prevents a webpage from one domain from accessing data on another domain. Origin is determined by protocol, domain, and port. Different subdomains or ports count as different origins.

Origin Header

When a browser makes a cross-origin request, it sends an Origin header indicating the source domain. The server uses this header to decide whether to allow the request, responding with Access-Control-Allow-Origin and other CORS headers.

Access-Control-Allow-Origin

This header specifies which origins may access the resource. It can contain a specific domain like https://app.example.com or a wildcard (*) for 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. The browser may only use methods explicitly allowed.

Access-Control-Allow-Headers

This header indicates which additional headers the client may send in the request. Standard headers like Content-Type, Accept, or Authorization may need explicit permission if they’re custom headers.

Access-Control-Allow-Credentials

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

Preflight Request

For complex cross-origin requests, the browser first sends an OPTIONS request, known as a preflight. The server responds with permitted methods, headers, and origins. Only then does the browser send the actual request. Preflight requests are triggered for methods like PUT or DELETE, or when custom headers are used.

Simple and Complex Requests

Simple requests use GET, HEAD, or POST with specific content types and standard headers. They require no preflight. Complex requests use other methods, custom headers, or content types and trigger a preflight.

CORS and Security Risks

Incorrect CORS configurations can lead to unauthorized access. Particularly dangerous are Access-Control-Allow-Origin: * on APIs that use credentials, dynamically echoing the Origin header without validation, and allowing unsafe methods. Attackers can exploit such mistakes to steal data from the browser.

CORS in API Configuration

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

Debugging CORS

CORS errors in browsers often lack detailed information. Browser developer tools and network logs help you investigate preflight and main requests. Server-side logs should record Origin headers and responses.

Practical Example

A web application at https://app.example.com accesses an API at https://api.example.com. The API must allow CORS for this 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 after that does the browser send the actual PUT request. This way, CORS ensures only authorized origins can access the API.

FAQ: CORS for APIs

1. What is CORS?

CORS stands for Cross-Origin Resource Sharing. It’s 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 only from the same domain. 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 permitted origins, methods, and headers.

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

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

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

Access-Control-Allow-Credentials allows cookies, HTTP authentication, or client certificates to be sent with cross-origin requests. When set to true, the Origin header cannot be a wildcard—it 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, and certain content types trigger a preflight. Simple GET, HEAD, and POST requests typically do not.

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

A wildcard allows any origin. For APIs with credentials or sensitive data, this can lead to unauthorized access. A whitelist of 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 specifies which additional headers the client may send in a cross-origin request. Custom headers like Authorization often need explicit permission.

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 the result of a preflight request. This reduces repeated OPTIONS requests.

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

Postman and similar tools don’t enforce CORS because they lack the Same-Origin Policy. CORS is a browser security mechanism that applies only in browsers.

14. What is dynamic origin mirroring?

Dynamic origin mirroring means the server simply echoes back the client’s Origin header. This is unsafe because it allows every origin and is equivalent to a wildcard.

15. How do you test CORS correctly?

Test CORS directly in the browser using different origins. Developer tools show preflight and main requests. Additionally, verify that credentials aren’t 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

If you’d like 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