🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
If you’ve ever worked on a Spring Boot backend paired with a React, Angular, or Vue frontend, chances are you’ve run into that dreaded error:
Access to fetch at 'http://localhost:8080/api/data' from origin 'http://localhost:3000'
has been blocked by CORS policy.It’s the bane of many frontend-backend integrations — CORS (Cross-Origin Resource Sharing) errors that break communication, confuse newcomers, and waste hours of debugging time.
What if fixing it didn’t require a complex setup or custom headers?
Here’s the good news: one clean CORS configuration in Spring Boot can solve all these problems — across dev, staging, and production — without exposing your app to security risks.
Let’s break it down.
What Is CORS, and Why Does It Block Your Requests?
CORS is a browser security mechanism. It prevents JavaScript on one origin (say, localhost:3000) from making requests to another origin (localhost:8080) unless the server explicitly allows it.
While it protects users from malicious cross-site attacks, it can also block legitimate communication between your frontend and backend during development or in microservice setups.
🚫 Common Symptoms of CORS Issues
- Fetch or Axios requests from frontend apps fail
- Preflight (OPTIONS) requests return
403 Forbidden - Authentication tokens aren’t sent or accepted
- Errors only happen in browsers — not Postman or cURL
The cause? Your Spring Boot backend doesn’t know it’s supposed to allow requests from your frontend origin.
The Cleanest Fix: Global CORS Mapping in Spring Boot
The most robust and maintainable way to handle CORS in Spring Boot is by using a WebMvcConfigurer bean.
✅ Add This One Config:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // Apply to all paths
.allowedOrigins("http://localhost:3000") // Frontend origin
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}Why This Works
addMapping("/**"): Applies to all endpoints in your appallowedOrigins(...): Only allows requests from your frontend (can be multiple origins)allowedMethods(...): Supports all major HTTP verbsallowCredentials(true): Allows cookies or Authorization headers to be sentallowedHeaders("*"): Accepts any custom headers (likeAuthorization,Content-Type, etc.)
This configuration lives in a single place, scales well across endpoints, and can be easily extended for multiple environments or microservices.
Real-World Example: React + Spring Boot
React app making a request:
fetch("http://localhost:8080/api/products", {
method: "GET",
credentials: "include", // Needed if using cookies
headers: {
"Content-Type": "application/json"
}
});Spring Boot backend returns:
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: trueThe browseraccepts the response. No CORS error. Request successful.
🛡 Security Note
You might be tempted to write:
.allowedOrigins("*")That will work, but it’s not secure — especially if you’re using allowCredentials(true) (which Spring will reject if * is used).
Use explicit origins (http://localhost:3000, https://yourfrontend.com) to avoid exposing your backend to untrusted sources.
Handling Multiple Frontend Origins
For environments like dev, staging, and production:
.allowedOrigins(
"http://localhost:3000",
"https://staging.frontend.com",
"https://www.frontend.com"
)Or load them from application.properties:
cors.allowed-origins=http://localhost:3000,https://frontend.comThen bind using @ConfigurationProperties or @Value in your config class.
Alternative: Controller-Level CORS (Not Recommended for Large Apps) using @CrossOrigin annotation
You can also add CORS config per controller:
@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/api")
public class ProductController {
...
}This is fine for small or isolated APIs, but becomes hard to maintain across multiple controllers and environments.
Prefer global config unless you have a specific reason to isolate CORS per controller.
Spring Security + CORS: The Common Gotcha
If you’re using Spring Security and still getting CORS errors after adding WebMvcConfigurer, the reason might be that Spring Security is overriding CORS behavior.
✅ Fix:
You must enable CORS in the security filter chain too:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors() // Enables CORS
.and()
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests()
.anyRequest().permitAll();
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("http://localhost:3000"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("*"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}Important:
- When using Spring Security,
@CrossOriginandWebMvcConfigureralone won’t work. - The security filter chain must include
cors()and aCorsConfigurationSource.
Debugging CORS Issues
✅ Use Browser DevTools
- Open the Network tab
- Click on the failed request
- Check Response Headers
- Look for missing
Access-Control-Allow-Originor mismatched values
✅ Use cURL with Origin Header
curl -H "Origin: http://localhost:3000" \
-H "Access-Control-Request-Method: GET" \
-X OPTIONS http://localhost:8080/api/products -vIf the response doesn’t include the proper CORS headers, the backend is misconfigured.
Summary: One CORS Config to Rule Them All

Conclusion
CORS is one of the most misunderstood issues in modern web development — not because it’s complex, but because the fix is often misplaced.
Spring Boot makes it easy to configure CORS the right way. With just one configuration class, it’s possible to:
- Eliminate development-time errors
- Enable secure cross-origin requests
- Scale from local testing to production deployments
No more jumping through hoops or disabling browser security. Just clean, declarative configuration.
My Top and Bestseller Udemy Courses. The sale is going on with a 70 - 80% discount. The discount coupon has been added to each course below:
Build REST APIs with Spring Boot 4, Spring Security 7, and JWT
[NEW] Learn Apache Maven with IntelliJ IDEA and Java 25
ChatGPT + Generative AI + Prompt Engineering for Beginners
Spring 7 and Spring Boot 4 for Beginners (Includes 8 Projects)
Available in Udemy for Business
Building Real-Time REST APIs with Spring Boot - Blog App
Available in Udemy for Business
Building Microservices with Spring Boot and Spring Cloud
Available in Udemy for Business
Java Full-Stack Developer Course with Spring Boot and React JS
Available in Udemy for Business
Build 5 Spring Boot Projects with Java: Line-by-Line Coding
Testing Spring Boot Application with JUnit and Mockito
Available in Udemy for Business
Spring Boot Thymeleaf Real-Time Web Application - Blog App
Available in Udemy for Business
Master Spring Data JPA with Hibernate
Available in Udemy for Business
Spring Boot + Apache Kafka Course - The Practical Guide
Available in Udemy for Business
Comments
Post a Comment
Leave Comment