Fix Spring Boot CORS Error (Angular / React) — Production-Safe Guide

CORS (Cross-Origin Resource Sharing) errors are one of the most persistent and confusing issues developers face when integrating modern frontend frameworks like Angular and React with a Spring Boot backend.

You may see errors such as:

Access to fetch at 'http://localhost:8080/api/users' from origin 'http://localhost:3000' has been blocked by CORS policy.

Or:

No 'Access-Control-Allow-Origin' header present on the requested resource.

These are not Spring errors — they’re browser security mechanisms rejecting your call because it violates same-origin policy.

This production-safe guide explains:

  • What CORS really is
  • Why browsers block certain requests
  • How to fix CORS properly in Spring Boot
  • How to do it securely in production
  • Angular and React specific examples

What Is CORS (Explained Simply)

CORS stands for Cross-Origin Resource Sharing — a browser security feature that restricts web pages from making requests to a different domain or port than where the page was served.

For example:

FrontendBackend
http://localhost:3000http://localhost:8080

This is considered cross-origin, and by default, browsers block such requests unless the server explicitly allows them.

Important to remember:

CORS is enforced by the browser — not by Spring Boot.

This is why tools like Postman or cURL do not show CORS errors, but browsers do.

Why CORS Errors Occur with Angular or React

Modern frontend applications often run on development servers such as:

  • Angular → http://localhost:4200
  • React → http://localhost:3000

When these apps call a Spring Boot API on a different origin:

  • Browser initiates a preflight request (OPTIONS)
  • It checks whether the server allows the actual request
  • If the server does not send the correct headers → request is blocked

Common Causes

✔ No CORS headers sent on preflight
✔ Spring Security filter ordering
✔ Credentialed requests (withCredentials)
✔ Wildcard origin used insecurely
✔ Allowed methods/headers mismatch

How Spring Boot Handles CORS (Production-Safe)

Spring Boot provides multiple ways to configure CORS.
The recommended production-safe approach is global configuration, not ad-hoc @CrossOrigin everywhere.

Global CORS Configuration (Best Approach)

Using WebMvcConfigurer

@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://your-frontend.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}

Production rule of thumb:

✔ Only allow trusted domains
✔ Avoid "*"
✔ Limit methods and headers as much as possible

Fixing CORS When Using Spring Security

If your application uses Spring Security, CORS configuration must be integrated with the security filter chain.

Without this, Spring Security may block preflight requests before your global CORS config can take effect.

Example Spring Security CORS Setup

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated()
);

return http.build();
}
}

Key points:

✔ Call .cors() before security rules
✔ Explicitly allow OPTIONS requests
✔ Do not disable CSRF unless intentional

Angular-Specific CORS Notes

Angular’s HttpClient often sends:

  • Custom headers
  • JSON content type
  • Authentication tokens

This triggers preflight (OPTIONS) before the main request.

If your backend does not handle OPTIONS correctly, the browser will block your calls.

Angular Example

this.httpClient.get('/api/users', { withCredentials: true });

Make sure Spring Boot’s CORS config:
✔ Allows credentials
✔ Matches origin exactly
✔ Supports required methods

React-Specific CORS Notes

React apps using fetch() or Axios may send:

fetch('http://localhost:8080/api/users', {
credentials: 'include',
headers: {
'Content-Type': 'application/json'
}
});

React’s credentials: 'include' will trigger a CORS preflight unless the backend explicitly allows credentialed requests.

Your Spring Boot CORS configuration must include:

.allowCredentials(true)

Why Not Use @CrossOrigin("*") Everywhere?

Using @CrossOrigin("*") or "*" for allowed origins is easy during development, but dangerous in production because:

❌ Opens your API to any origin
❌ Makes API vulnerable to CSRF attacks
❌ Complicates monitoring and security audits

Use trusted domains — not wildcards.

How to Debug CORS Issues (Production Tips)

Browser DevTools

✔ Look at Network tab
✔ Check the OPTIONS preflight request
✔ Inspect response headers
✔ Confirm correct Access-Control-Allow-Origin

Required response headers for CORS:

Access-Control-Allow-Origin: https://your-frontend.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true

Related Spring Boot Guides

Understanding the request lifecycle, profiles, and security helps fix CORS more effectively:

Summary

CORS errors in Spring Boot are not bugs — they’re browser security policies at work.
Fixing them requires:

✔ Understanding how browsers initiate preflight requests
✔ Correctly configuring Spring Boot (global CORS + Spring Security)
✔ Allowing trusted origins only
✔ Using environment-specific rules for production

With this production-safe approach, your Angular and React frontends will work smoothly with your Spring Boot backend without compromising security.

Leave a Comment

Your email address will not be published. Required fields are marked *