I have a backend application in Spring Boot running on port 8080, and frontend React.js project running on port 3000. We are sending a request from React.js (port 3000) to Spring Boot /authenticate endpoint (port 8080) where it authenticates the login information and sends back a response. This works perfectly when running both application on my own computer. However, we need to use an vm and run the applications in separate docker containers. When the frontend is in an container, only the host can reach port 3000. Here is the Dockerfile we used for the frontend:
FROM node:alpine
RUN mkdir /app
WORKDIR /app
COPY package.json /app
COPY package-lock.json /app
RUN npm install
RUN npm install cors
COPY . /app
CMD ["npm", "start"]
This is the docker run command we used:
docker run -it -p 3000:3000 --name frontend-react group09/frontend-react
To allow other users than the host to reach port 3000, we used a nginx proxy to route traffic from port 80 to 3000. HOWEVER, when we did this we got an ERR: BLOCKED BY CLIENT message in the console. I will also attach the SecurityConfig we used in Spring Boot:
@Override
protected void configure(HttpSecurity http) throws Exception {
// Allow JWT authentication
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Enable our JWT authentication filter
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
// Necessary authorization for each endpoint will be configured by each method, using @PreAuthorize
}
Cors config:
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000","http://localhost:3000/","http://localhost:3000/login"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "withCredentials","content-type", "x-auth-token","Access-Control-Allow-Credentials","access-control-allow-origin","Access-Control-Allow-headers"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token","set-cookie"));
configuration.setMaxAge(Duration.ofSeconds(5000));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
I really appriecate any tips on how to resolve this problem. We are pretty sure the problem isn’t within the code, as it runs completely fine when doing it outside of docker containers.
2
Answers
I figured out the problem after solid 20 hours. Basically we had to setAllowedOrigins to *, so that all IPs are allowed. To do this you also have to setAllowCredentials to false.
Have you checked the
referrer
field in the request? Most probably, it is not localhost in this case, but rather you domain name.In this is the case, you need to add
frontend_domain_name:3000
to your cors policyallowed origin
field.Update: the answer which suggests to set
allowed origin
to *, actually, disables CORS as it allows all domains access your backend code, not just your frontend part.The correct way would be to add
your_frontend_domain_name:3000
asallowed origin
. This way your backend will be accessible only by users who are working through your frontend website.