Understanding Same-Origin Policy and CORS in Web Development
This article explains the same‑origin policy, its role in protecting web applications, how browsers enforce it through DOM, web‑data, and network restrictions, and how Cross‑Origin Resource Sharing (CORS) and preflight requests enable controlled cross‑origin communication while maintaining security.
In modern browsers, resources such as JavaScript, images, audio, and video can be loaded from any origin, but unrestricted access leads to security risks like XSS, SQL injection, OS command injection, HTTP header injection, and CSRF.
The fundamental protection mechanism is the same‑origin policy , which restricts how a document or script from one origin can interact with resources from another origin. Two URLs are considered same‑origin only when their protocol, host, and port all match.
Protocol (e.g., HTTP, HTTPS)
Host (the networked computer or device)
Port (process‑to‑process communication endpoint)
The policy manifests in three areas:
DOM access restriction: Scripts cannot read or manipulate the DOM of a page from a different origin.
Web data restriction: XMLHttpRequest and Fetch API calls are limited to the same origin unless CORS is used.
Network communication restriction: Browsers block cross‑origin network responses unless explicitly allowed.
To enable safe cross‑origin requests, browsers implement Cross‑Origin Resource Sharing (CORS) . The server includes specific HTTP headers in its response to indicate which origins are permitted.
Simple Requests
A request is considered simple and does not trigger a preflight OPTIONS request if it meets all of the following conditions:
Uses only GET, HEAD, or POST methods.
Contains only allowed headers such as Accept, Accept‑Language, Content‑Language, Last‑Event‑ID, and Content‑Type (limited to application/x‑www‑form‑urlencoded, multipart/form‑data, or text/plain).
Does not use a ReadableStream object.
Does not include custom request headers.
No event listeners are registered on XMLHttpRequestUpload.
Preflight Requests
For non‑simple requests, the browser first sends a preflight OPTIONS request to determine if the actual request is safe. The preflight includes two special headers:
Access-Control-Request-Method : the HTTP method that will be used (e.g., POST).
Access-Control-Request-Headers : a comma‑separated list of custom headers the actual request will send (e.g., content-type, x‑secsdk‑csrf‑token).
The server responds with corresponding Access-Control-Allow-* headers, such as:
Access-Control-Allow-Origin : specifies the allowed origin (cannot be "*" when credentials are included).
Access-Control-Allow-Methods : lists permitted HTTP methods.
Access-Control-Allow-Headers : lists permitted custom headers.
Access-Control-Max-Age : optional cache duration for the preflight response.
After a successful preflight, subsequent actual requests include an Origin header, and the server must again include Access-Control-Allow-Origin in its response.
When credentials (e.g., cookies) are involved, the server must not use a wildcard "*" for Access-Control-Allow-Origin or other wildcard values for Access-Control-Allow-Headers and Access-Control-Allow-Methods ; instead, it must specify the exact origin to prevent malicious sites from accessing sensitive data.
In summary, the same‑origin policy protects users by isolating content from different origins, while CORS provides a controlled way to relax these restrictions when needed, using simple request rules, preflight checks, and explicit server‑side header configurations.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.