한국어 | English | 日本語
Senior Web Application Developer (8.8+ years)
Tech & Dev
engineering
Focusing on web frontend and backend development

CORS - A Complementary Policy to SOP for Cross-Origin AJAX Calls

When I first delved into web development, CORS was one of the initial challenges I encountered. CORS itself isn't an issue but a protocol that informs developers when a request doesn't adhere to its rules. It's a fundamental security component for web browsers. While linking external images for a blog doesn't pose a security risk, retrieving dynamic resources from external sources via AJAX calls like POST or PUT can alter server state, creating security vulnerabilities. Therefore, calls that modify server state (including client state changes via cookie headers) must be rigorously verified to ensure they are genuinely intended by the developer. Otherwise, malicious script injection into a blog could trigger unwanted AJAX calls to manipulate server resources on an external domain.
Web browsers display resources fetched from both the same domain and external domains for versatile content utilization. Resources from the same domain are 'Same Origin,' while those from different domains are 'Cross Origin.' For minimal security, browsers implement the Same-Origin Policy (SOP), which allows cross-origin fetching for simple resources. However, AJAX calls, which can manipulate external domain resources, are blocked by SOP due to potential risks. CORS is an additional policy that enables AJAX requests to external domains that would otherwise be blocked by SOP.

Browser’s Same-Origin Policy (SOP)

HTTP requests in browsers fundamentally adhere to the Same-Origin Policy (SOP).

Due to its name, the Same-Origin Policy might be misunderstood as strictly requiring the calling domain and the resource-providing domain to be identical. However, it exceptionally permits the following cases where security is not compromised. Note that Cross-site, Cross-domain, and Cross-origin all refer to the same concept.

AJAX (Asynchronous JavaScript and XML)

What is AJAX? It supports asynchronous JavaScript for server communication, forming the foundation for technologies like axios and fetch, commonly used in frontend development to retrieve data from servers. Most major web browsers today incorporate the XMLHttpRequest (XHR) object to handle asynchronous data requests to servers. Although not a W3C standard, its implementation varies across browsers but universally relies on the XHR object. This XHR object allows requesting or receiving data from the server and updating only a portion of the page, even after the entire web page has loaded.

Introduction of CORS - For Cross-origin AJAX Calls

AJAX can call any server, allowing it to fetch information from both same-domain servers and different domains. While it would be ideal if only developer-intended AJAX calls were possible, there’s a vulnerability known as CSRF (Cross-site Request Forgery), which involves tricking users into executing malicious scripts that trigger unwanted AJAX calls to other domain servers.

Due to such vulnerabilities, the SOP policy should block AJAX. However, despite AJAX not being a W3C standard, it’s used as a de facto asynchronous standard, leading to the introduction of CORS as an exception policy. The CORS policy provides a mechanism for cross-verification between the client (browser) and the server to determine if an AJAX call is intended, thereby preventing malicious AJAX requests.

Adhering to the CORS policy permits Cross-origin calls via AJAX.

CORS Policy Verification Procedure

CORS is a mandatory HTTP policy included in the browser’s implementation specification, and like SOP, the browser determines whether the CORS policy is met. The browser receives the response from the server but discards it if, after analysis, a CORS violation is detected. Therefore, this policy does not apply to server-to-server communication that bypasses the browser.

Types of CORS Requests

Browsers classify AJAX calls into two types, applying different CORS policy verification procedures. This categorization appears to be for documentation purposes, and simply put, it can be understood as follows:

For a detailed understanding, let’s examine the two types of combinations:

Simple/Preflight Request

If the HTTP method used in AJAX is GET or HEAD, which are for simple retrieval and cannot manipulate the server, CORS verification is performed by receiving the actual response and checking its included headers. However, if the method changes the server’s state (POST, PUT, DELETE) or includes custom headers (e.g., for cookie storage), a preflight request (Method = OPTIONS) is sent before the actual request to perform CORS verification by receiving only headers, without the actual response body. Once CORS verification is complete, the actual request is then sent to modify the server’s state.

Simple Request

Since these are Methods that cannot manipulate the server, the client sends the actual request and only verifies the match of (1) Allowed Origin.

Preflight Request

Since these are Methods that can manipulate the server, the client sends a preflight request instead of the actual request, and verifies the match of all three: (1) Allowed Origin, (2) Allowed Method, and (3) Allowed Header.

Credentials

Credentials refer to Cookies, Authorization Headers, or TLS client certificates. When a client requests by activating “credential mode” via XMLHttpRequest.withCredentials or the credentials option in the Fetch API Request() constructor, the server sends “credential information headers” containing values to the client. At this point, the server also indicates, via the “CORS header” below, whether the client can view the “credential information header” values. If this “CORS header” is true, the browser exposes the “credential information headers” to the client; if false or absent (defaulting to false), it discards all “credential information headers” and hides them from the client.

It’s important to note that for Credential requests, the Access-Control-Allow-Origin value in the CORS header must not be *. A specific domain, such as a.com, must be provided.

Examining with Examples

Simple Request

When an AJAX call is made from domain a.com to domain b.com:

Preflight Request

When an AJAX call is made from domain a.com to domain b.com:

Additional CORS-Related Response HTTP Headers

Unlike Access-Control-Allow-Methods or Access-Control-Allow-Headers which we’ve already examined, there are a few additional CORS-related headers that the server sends in its response, which I’ll explain to conclude.

Access-Control-Max-Age

For Preflight Requests, repeatedly sending and receiving OPTIONS preflight requests takes time before the actual result can be returned. Therefore, the server can specify how long the CORS response header values for preflight requests can be cached by the browser.

Access-Control-Expose-Headers

While Allow in Access-Control-Allow-Headers signifies which headers the server allows the client to send, the Expose header explicitly defines which headers sent by the server the browser is permitted to read.


  1. HomoEfficio : Cross Origin Resource Sharing - CORS
  2. MDN : Same-Origin Policy
  3. MDN : Cross-Origin Resource Sharing (CORS)
  4. MDN : Access-Control-Allow-Credentials
  5. Youtube : CORS in 100 Seconds
CORS - A Complementary Policy to SOP for Cross-Origin AJAX Calls
Author
Aaron
Posted on
Licensed Under
CC BY-NC-SA 4.0
CC BY-NC-SA 4.0
More in this category
Recent posts
The Erosion of Conversational Muscle and Communication Styles by LLM Filters
In an era where LLM tools, which filter out conversational impoliteness and deliver refined responses, have become commonplace, are we truly engaging in more thoughtful conversations? This article examines the phenomenon of conversational ability, which should be honed through countless failures in real-time communication, degenerating due to reliance on external tools. It further explores the potential societal anxieties and shifts in generational behavioral patterns that this trend may bring.
Optimal Timing and Strategy for Salary Negotiation with Senior Candidates
Salary negotiation is more than just an exchange of figures; it's a strategic dance of psychological timing. This analysis explores why engaging in a gradual negotiation process from the initial stages of recruitment, rather than waiting until after a final offer (when candidates tend to adopt a more calculative stance), proves more efficient for companies and fosters a more honest sharing of resources.
The Limits of the Rule of Law and Human Diversity
The belief that all human actions can be regulated by a single legal system may be an act of hubris. This article offers a sharp analysis of the paradox of the rule of law faced by humanity, which, having escaped the hierarchical controls of the Middle Ages, has now embraced infinite modern freedom. It further examines the deepening social coercion and the demonization of others that arise under the guise of diversity.
토스트 예시 메세지