How to Fix Cross-Origin Errors
Cross-Origin errors are among the most common challenges we face when building web applications that connect frontends and backends hosted on different origins. Browsers enforce strict security mechanisms that can block such requests, leading to the infamous CORS policy error.
In this guide, we’ll explore the Same Origin Policy (SOP), the foundation of browser security, and how Cross Origin Resource Sharing (CORS) extends its flexibility.
1. Same-Origin Policy (SOP)
The Same-Origin Policy (SOP) was developed as a core security mechanism in browsers to protect sensitive resources from malicious attacks. It ensures that scripts running on one website cannot access the data or resources of another website unless both share the same origin.
Understanding Same-Origin
Two URLs are considered to have the same origin if they share the same protocol, domain, and port number.
| URL | Origin |
|---|---|
| http://javacodegeeks.com | http + javacodegeeks.com + (default 80) |
| https://javacodegeeks.com | https + javacodegeeks.com + (default 443) |
| http://api.javacodegeeks.com | Different domain (subdomain differs) |
| http://javacodegeeks.com:8080 | Different port |
If any one of these three components differs, the two resources are treated as cross-origin, and by default, the browser will block access between them.
Why SOP Matters
SOP is intentionally restrictive because it prevents unauthorized access to cookies, sessions, or other sensitive data. Without it, any website could execute malicious JavaScript to read private information from other domains, leading to Cross-Site Scripting (XSS) or Cross-Site Request Forgery (CSRF) attacks.
However, while SOP provides robust security, it can also become a limitation when legitimate applications need to communicate across trusted domains, such as when a React frontend hosted on localhost:3000 needs to interact with an API at localhost:8080.
To overcome these limitations safely, Cross-Origin Resource Sharing (CORS) was introduced.
2. Cross-Origin Resource Sharing (CORS)
Cross-Origin Resource Sharing (CORS) extends the Same-Origin Policy by allowing controlled access between different origins. Instead of completely blocking requests from one origin to another, CORS enables the server to declare which origins are permitted to access its resources explicitly.
How CORS Works
When a web application on one origin tries to make a request to another origin, the browser sends an HTTP preflight request using the OPTIONS method. This request checks whether the target server allows the cross-origin call.
The server then responds with specific HTTP headers that define permissions, such as:
Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Content-Type
If the response headers indicate that the requesting origin is allowed, the browser proceeds with the actual request. Otherwise, the browser blocks it, resulting in a CORS error.
Security Considerations
CORS offers flexibility, but it must be implemented with caution. Incorrect configurations, such as allowing all origins using Access-Control-Allow-Origin: *, can expose APIs to malicious requests. While CORS is designed to enable trusted cross-origin communication, it remains a security feature, not a workaround. We must configure it properly to maintain protection while enabling legitimate data sharing.
3. Example: Client and Server Interaction
To better understand how CORS errors occur, let’s demonstrate the problem using a simple HTML + JavaScript frontend and an Express.js backend. The frontend will attempt to fetch data from the backend API hosted on a different port, triggering a CORS policy error.
Backend (server.js)
// server/app.js
const express = require("express");
const app = express();
const PORT = 3000;
app.get("/api/message", (req, res) => {
res.json({ message: "Hello from the backend API!" });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
This backend exposes a simple /api/message endpoint returning a JSON message. It’s hosted on port 3000, which makes it a different origin from the frontend that will run on another port (e.g., 8080).
Starting the Backend
Before testing, ensure that Node.js is installed. Then, follow these steps to start the backend server. Initialize the project (if not already):
npm init -y
Install Express.js:
npm install express
Run the server:
node app.js
You should see this message in your terminal:
Server running on http://localhost:3000
Keep this server running while you start the frontend.
Frontend (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CORS Demo</title>
</head>
<body>
<h1 id="message">Loading...</h1>
<script>
fetch("http://localhost:3000/api/message")
.then(response => response.json())
.then(data => {
document.getElementById("message").textContent = data.message;
})
.catch(error => {
console.error("Error:", error);
document.getElementById("message").textContent = "CORS Error! Check console.";
});
</script>
</body>
</html>
Running the Frontend on a Local Server
Instead of opening the HTML file directly, serve it through a local HTTP server to simulate a realistic client environment. If you have Node.js installed, run this command inside the directory containing index.html:
npx http-server .
This starts a local server, typically on http://127.0.0.1:8080/, depending on port availability.
Testing the Setup
Open http://127.0.0.1:8080 in your browser. You’ll likely see this error in the console:
This occurs because the Same Origin Policy (SOP) prevents the frontend (running on port 8080) from requesting data from a backend on a different port (3000). The browser enforces this rule to prevent unauthorized cross-domain access.
In the next section, we’ll fix this by enabling CORS on the backend, allowing specific origins to access the server’s resources securely.
4. How to Fix CORS Policy Errors
CORS errors are resolved by configuring the server to send the correct CORS headers. The fix depends on your backend framework.
Fix for Express.js
Install the official CORS middleware:
npm install cors
Then update your server configuration:
// server/app.js
const express = require("express");
const cors = require("cors");
const app = express();
const PORT = 3000;
// Enable CORS for a specific origin
app.use(cors({ origin: "http://127.0.0.1:8080" }));
app.get("/api/message", (req, res) => {
res.json({ message: "Hello from the backend API!" });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
The cors middleware automatically sets the Access-Control-Allow-Origin header, allowing only the specified origin to access the backend. You can set origin: '*' for local testing, but in production, you should always restrict access to trusted domains.
5. Fix for Spring Boot
For Java backends, CORS can be enabled using the @CrossOrigin annotation or a global configuration class.
Controller Example
@RestController
public class MessageController {
@CrossOrigin(origins = "http://localhost:8080")
@GetMapping("/api/message")
public String getMessage() {
return "Hello from the Spring Boot backend!";
}
}
Global CORS Configuration
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
This configuration tells Spring MVC to allow all routes (/**) to accept cross-origin requests from http://localhost:8080. It also specifies which HTTP methods are permitted and allows credentials (cookies, authorization headers) to be shared.
Configuring CORS in Spring Security
If your application uses Spring Security, you must also enable CORS in the security configuration. Without doing so, Spring Security may block requests even if CORS is already defined globally in WebMvcConfigurer. Here’s how we can configure CORS within our Spring Security setup.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults()) // Enable CORS support
.csrf(csrf -> csrf.disable()) // Disable CSRF for simplicity in REST APIs
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:8080"));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
In this setup, the CorsConfigurationSource defines allowed origins, methods, and headers, similar to the global configuration, but integrates directly into Spring Security’s filter chain; the .cors(Customizer.withDefaults()) call activates the CORS filter, while .csrf().disable() is often used in REST APIs to simplify requests from external clients, and together they ensure that only requests from http://localhost:8080 can access the backend endpoints.
6. Conclusion
The Same-Origin Policy (SOP) serves as a foundation for browser security, protecting users from cross-domain attacks. However, it also limits legitimate interactions between trusted web applications. Cross-Origin Resource Sharing (CORS) was designed to provide a controlled and flexible way to bypass these restrictions safely.
When properly configured, CORS allows secure communication between different origins, enabling modern web applications to function seamlessly while maintaining strong security boundaries.
Key Takeaways:
- SOP restricts resource sharing between different origins for security.
- CORS allows controlled access for trusted cross-origin interactions.
- Always configure CORS precisely. Avoid using
*in production. - Use frameworks’ built-in CORS mechanisms (like Express middleware or Spring Boot configuration) for best results.
With a clear understanding of how to fix cross-origin errors, we can build secure, high-performing web applications that communicate effectively across domains.
7. Download the Source Code
This article explained how to fix cross origin errors and understand the underlying CORS policy in web applications.
You can download the full source code of this example here: how to fix cross origin errors


Thanks for the clear explanation.