How to fix CORS error blocked by CORS policy in Spring Boot

The browser blocks requests from my frontend app to my Spring Boot REST API:

Access to XMLHttpRequest at 'http://localhost:8080/api/users'
from origin 'http://localhost:3000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

The API works fine when called from Postman, but fails in the browser. How do I configure CORS in Spring Boot?

Solution

Spring Boot blocks cross-origin requests by default for security reasons. For a quick fix on a specific controller, add the @CrossOrigin annotation:

@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:3000")
public class UserController {

    @GetMapping
    public List<User> getUsers() {
        return userService.findAll();
    }
}

For a global configuration that applies to all controllers, implement WebMvcConfigurer:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("http://localhost:3000")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}
Alternative #1

If you use Spring Security, the CORS configuration from WebMvcConfigurer may be ignored because Spring Security's filter chain intercepts requests before they reach the MVC layer. You must also enable CORS in your security configuration:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(csrf -> csrf.disable())
            // ... rest of your security config
            ;
        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;
    }
}
Alternative #2

For development environments, you can proxy API requests through the frontend dev server instead of configuring CORS on the backend. With Next.js, add a rewrite rule in next.config.js:

// next.config.js
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'http://localhost:8080/api/:path*',
      },
    ]
  },
}

Requests from the browser go to http://localhost:3000/api/users, and Next.js proxies them to http://localhost:8080/api/users server-side. Since the request originates from the same origin as far as the browser is concerned, no CORS headers are needed.

Last modified: April 16, 2026
Stay in the loop
Subscribe to our newsletter to get the latest articles delivered to your inbox