Comparisons
Pairs that get conflated in real conversations, and in real pull requests. Neither column wins — what decides is the requirement. Each record leads with the confusion, because the confusion is the reason the record exists.
CORS vs Authentication
CORS is routinely described as "securing the API", and the wildcard origin is treated as a vulnerability while a missing authorization check is treated as a configuration detail. This is backwards. CORS is enforced by the browser, on the response, for scripted cross-origin reads — it is a relaxation of the same-origin policy, not a lock. It does not stop the request from reaching your server (a simple request is sent and executed; only the response is withheld from the script), and it does not exist at all outside a browser: curl, a script, a mobile app and a proxy ignore it entirely. So a CORS-restricted endpoint with no authorization is a public endpoint. The practical consequence for a frontend engineer is that the console error is a browser telling you *this origin may not read that response*, and the fix always lives in the other origin's response headers — never in your fetch options, and never in a proxy you added to make the message go away without understanding it.
Never as a security control. Configure it so that browsers running your frontend on one origin are permitted to read responses from another, and no wider than that.
Always, on every request that touches anything non-public — regardless of which origin claims to be calling, and regardless of what the CORS headers say.
| Dimension | CORS — a browser policy on reading cross-origin responses | Authentication and authorization — server-side checks on who is calling and what they may do |
|---|---|---|
| Enforced by | The browser, on the client | The server, on every request |
| Protects | The user, from a page reading another origin's data as them | The resource, from anyone not permitted to touch it |
| Applies to | Scripted cross-origin requests in a browser | Every caller, including ones with no browser at all |
| Does it stop the request | Often no — the request runs and the response is withheld | Yes, that is the point |
| Bypassed by | Any non-browser client | Nothing, if it is implemented correctly |
| Where the fix lives | The responding origin's headers | The handler, and the object-level check inside it |
| Wildcard means | Any origin may read public responses; credentials are then refused | Nothing — it is not an authorization statement |