Understanding CORS in Modern Web APIs
Understanding CORS in Modern Web APIs
If you’ve ever stared at a browser console screaming “No ‘Access-Control-Allow-Origin’ header is present on the requested resource,” you’re not alone. CORS remains one of the most misunderstood topics for developers building modern web applications - especially when working with .NET backends and frontend frameworks.
You probably have a few burning questions right now:
- Why does my API work perfectly in Postman but fail in the browser?
- Is CORS the same as domain matching?
- And if CORS isn’t really security… then what is protecting my API?
Let’s clear up the confusion once and for all with practical examples, real-world explanations, and zero fluff.
Origin vs Domain – The Core Confusion Most Developers Miss
Here’s a question that trips up even experienced developers:
“If the domains are the same, why do I still get a CORS error?”
The answer is simple once you know the definition.
Origin = protocol + domain + port
Domain is not enough for CORS. The browser is extremely strict.
Real Examples That Make It Click
| URL | Origin | Same as https://eg.com? |
|---|---|---|
| https://eg.com | https://eg.com | Yes |
| https://sub.eg.com | https://sub.eg.com | No (different subdomain) |
| http://eg.com | http://eg.com | No (different protocol) |
| https://eg.com:8080 | https://eg.com:8080 | No (different port) |
| https://eg.com | https://eg.com | Yes |
Key takeaway: Even https://eg.com and https://sub.eg.com are completely different origins. The browser treats them as strangers.
Is CORS Actually a Server Feature?
This is the question that confuses almost everyone:
“If I fix CORS on my server, am I done?”
The surprising answer: No.
CORS is not enforced by your server. It is enforced only by the browser.
That’s why:
- Postman works
- curl works
- Backend-to-backend calls work
- Python scripts work
… but your JavaScript running in the browser gets blocked.
CORS is simply a browser safety mechanism.
Your server can return whatever headers it wants - the browser decides whether to allow the request.
If CORS Isn’t Security, Then What Actually Protects My API?
This is where most developers get it wrong.
You’ve probably asked yourself:
“If anyone can bypass CORS, why even bother with it?”
Exactly. CORS is not a security wall. Attackers can easily call your API using:
- Postman
- curl
- Custom scripts
- Proxy tools
Real API security comes from completely different layers:
- Authentication → JWT tokens or OAuth2
- Authorization → Role-Based Access Control (RBAC)
- API Gateway → Central place for validation (Ocelot, Kong, Azure API Management)
- Rate Limiting → Stop brute-force and abuse
- Input Validation → Block injection attacks
CORS is only there to protect users from certain cross-origin attacks. It does not protect your API.
Preflight Requests (OPTIONS) – The Step Most People Don’t Understand
Here’s another common question developers ask:
“Why is the browser sending an OPTIONS request before my actual PUT/PATCH/DELETE?”
That’s called a preflight request. The browser does it automatically for “non-simple” requests.
When Does a Preflight Happen?
- Methods: PUT, PATCH, DELETE (and sometimes POST)
- Custom headers (like
Authorization) - Content-Type other than
application/x-www-form-urlencoded,multipart/form-data, ortext/plain(e.g.,application/json)
Simple Preflight Flow Example
-
Preflight (Negotiation)
Browser sends:
OPTIONS /api/users/1
with headers asking:- Is PATCH allowed from my origin?
- Is the
Authorizationheader allowed? - Is my content-type allowed?
-
Server Responds
If approved, server returns properAccess-Control-Allow-*headers. -
Actual Request
Only then does the browser send the realPATCH /api/users/1request.
Think of preflight as the browser politely asking for permission before doing anything risky.
Common CORS Misconceptions (That Are Still Costing You Time)
Let’s bust a few myths you might still believe:
-
Myth: “A CORS error means my API is broken.”
Reality: Your API is usually working fine. The browser is just blocking the response. -
Myth: “Enabling CORS makes my API secure.”
Reality: Postman can still hit your API with zero issues. -
Myth: “If the domains match, I won’t have CORS problems.”
Reality: Remember the origin table above - protocol and port matter too.
Pro Tips from Real-World Projects
- Always test your APIs in both the browser and Postman during development.
- Never use
AllowAnyOrigin(or equivalent) in production - always whitelist specific origins. - When debugging PUT/PATCH failures, check the preflight OPTIONS response first.
- In .NET, configure CORS properly in your
Program.csor use an API Gateway like Ocelot for cleaner control. - Document your allowed origins clearly in your team’s internal wiki.
Final Summary – What You Should Remember
- CORS is a browser rule, not server security
- Origin is much stricter than domain
- Preflight requests are just the browser negotiating permissions
- Real protection comes from authentication, authorization, and proper API architecture
Happy coding, and may your CORS headers always be perfectly aligned.
Enjoyed this article? Share it with your network!