Introduction
If you've ever built a web app that fetches data from another server, chances are you've encountered CORS at least once. But don't worry! By the end of this blog, you'll know exactly what’s going on, why CORS exists, and how to handle it like a pro. 🚀
Let's start with a simple question: Why can't your browser just fetch data from any website anytime it wants?
Well, it used to—but that was a massive security risk. Imagine you visit a banking website while another tab is open to a malicious hacker site. Without security restrictions, that hacker site could secretly send requests to your bank's API impersonating you and steal your data. 😱
Enter Same-Origin Policy (SOP)
To prevent such attacks, browsers enforce the Same-Origin Policy (SOP), which blocks requests between different origins. The rule is simple: a web page can only make API requests to the same origin (same domain, protocol, and port) from which it was loaded.
For example:
✅ Allowed: https://bong.io → https://bong.io/api
❌ Blocked: https://bonk.io → https://api.by.com
This is where CORS (Cross-Origin Resource Sharing) comes in.
What is CORS?
CORS is a security feature that allows servers to declare which origins are permitted to access their resources. It’s all about HTTP headers! 🔥
Here’s how it works:
1️⃣ Your front-end (e.g., https://myapp.com) makes a request to an external API (https://api.example.com).
2️⃣ The browser automatically adds an Origin header to indicate where the request is coming from.
3️⃣ The server at api.example.com checks if it wants to allow requests from https://myapp.com.
4️⃣ If allowed, the server responds with:
Access-Control-Allow-Origin: https://myapp.com5️⃣ If this header is missing or doesn’t match the request's origin, the browser blocks the request, causing a CORS error. 😩
Types of CORS Requests
CORS requests are categorized into two main types:
1️⃣ Simple Requests ✅
A request is simple if:
- The method is GET, POST, or HEAD.
- It has no custom headers (like Authorization tokens).
- The content type is
application/x-www-form-urlencoded,multipart/form-data, ortext/plain.
If the server includes Access-Control-Allow-Origin, the request succeeds without extra steps.
2️⃣ Preflight Requests 🚀
For more complex requests (e.g., using PUT, DELETE, PATCH, or custom headers like Authorization), the browser sends a preflight request first.
A preflight request is an OPTIONS request sent before the actual request, asking the server:
- "Hey, do you allow requests from my origin?"
- "Are these headers and methods okay?"
If the server responds with the correct CORS headers, the actual request is sent!
Example of a preflight request:
OPTIONS /data HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: AuthorizationExpected server response:
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: AuthorizationHow to Fix CORS Errors ⚡
🛠️ Solution 1: Configure the Backend
If you control the backend, allow CORS by adding proper headers. Here's how to do it in Node.js (Express):
const cors = require('cors');
const app = require('express')();
app.use(cors({ origin: 'https://myapp.com' }));
app.get('/data', (req, res) => res.json({ message: 'Success!' }));
app.listen(3000);🛠️ Solution 2: Fix CORS in Spring Boot (Java)
If you're using Spring Boot, define a global CORS policy:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://bonk.io")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Authorization", "Content-Type");
}
};
}
}If you’re using Spring Security, allow CORS inside your security configuration:
http.cors();🛠️ Solution 3: Use a Proxy
If you can’t modify the backend, use a proxy to forward requests from the frontend to the backend, making them appear as same-origin.
Example using webpack devServer (React/Vite):
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
},
},
}🛠️ Solution 4: Use a CORS Browser Extension (For Development Only)
If you're working on a front-end project and don’t have access to backend configurations, use a CORS extension like CORS Everywhere for Chrome or Firefox. Just keep in mind this is only for debugging and development!
CORS vs CSRF (Important!)
A common misconception is that CORS protects against CSRF (Cross-Site Request Forgery), but it doesn’t!
- CORS controls which websites can access your APIs.
- CSRF is an attack where an attacker tricks an authenticated user into making unintended requests.
For CSRF protection, use CSRF tokens and SameSite cookies—we’ll cover this in an upcoming post! 🔥
Conclusion 🎯
By now, you should have a solid understanding of CORS: ✅ What CORS is and why it exists ✅ The difference between simple and preflight requests ✅ How to fix CORS issues using backend configurations, proxies, and extensions ✅ The difference between CORS and CSRF
CORS errors can be frustrating, but with the right approach, they’re easy to fix. Now, go build amazing web apps without CORS headaches! 🚀
Stay tuned for more deep dives into web security and API best practices! 🔥