Search code examples
reactjsspringcorsngrok

React frontend cannot communicate with Spring Boot backend because of CORS policy


I have exposed two services with ngrok to the internet with the following example url's:

  • frontend.eu.ngrok.io (React application)
  • backend.ru.ngrok.io (Spring Boot application with Kotlin)

The frontend tries to make an axios request to the backend with the following example url:

  • GET backend.ru.ngrok.io/helloworld

But the console prints the following error:

  • Access to XMLHttpRequest at 'backend.ru.ngrok.io/helloworld' from origin 'frontend.ru.ngrok.io' has been blocked by CORS policy...

When I make the request in an extra Chrome tab or from Postman it succeeds. So I know that the problem is with Chrome and it doesn't allow XMLHttpRequests from another origin to the backend but i tried to fix it inside my Spring Boot backend by annotating my endpoints with: @CrossOrigin

I also configured cors and added it to the security configuration (inspired by https://spring.io/blog/2015/06/08/cors-support-in-spring-framework):

@Configuration
@EnableWebSecurity
class WebSecurityConfig: WebSecurityConfigurerAdapter {

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http.cors()...
    }
}
@Configuration
class SimpleCorsConfiguration {
    @Bean
    fun corsConfigurer(): WebMvcConfigurer {
        return object : WebMvcConfigurerAdapter() {
            override fun addCorsMappings(registry: CorsRegistry) {
                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*")
                        .exposedHeaders("*")
                        .allowCredentials(false).maxAge(3600)
            }
        }
    }
}

What is the modern way of connecting a frontend and backend with each other and still pay attention to the correct CORS policy. I also guess the request doesn't even reach my backend, caused by Chrome and it's CORS policy. What am I doing wrong here?


Solution

  • The problem was with ngrok and the free plan. If you visit the site it displays a "warn page" with a nice hint to disable this page by setting the request header "ngrok-skip-browser-warning" to any value you want. So the temporary warning page from ngrok blocked my XMLHttpRequest from my frontend due to their CORS policy and therefore the request never reached my backend.

    To fix the problem just add the header in all your axios requests from the React frontend:

    axios.defaults.headers.common['ngrok-skip-browser-warning'] = "any value";