Home > Enterprise >  OPTIONS - 403 Forbidden - React consuming SpringBoot Rest API
OPTIONS - 403 Forbidden - React consuming SpringBoot Rest API

Time:03-18

I have a React application running locally consuming services of a SpringBoot application on development environment. On React we have a proxy server to change the origin from "localhost" to the development domain name "dev-web".

proxyServer.js

switch (TARGET) {
  ....
  default:
    target_url = "https://dev-web.com";
    break;
}
...
module.exports = {
  ...
  historyApiFallback: true,
  headers: {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Headers": "*",
    "Access-Control-Allow-Methods": "*",
  },
  proxy: {
    "/api/*": {
      changeOrigin: true,
      cookieDomainRewrite: "localhost",
      logLevel: "debug",
      target: `${target_url}`,

      onProxyReq: (proxyReq) => {
        if (proxyReq.getHeader("origin")) {
          proxyReq.setHeader("origin", `${target_url}`);
        }
      },
     secure: false,
     pathRewrite: {
       "^/api": "",
     },
   },
...

The problem is that when I try to make a GET request everything works, but when I try to make a POST request, it gives an error because before post, browser tries to make a OPTIONS request on preflight.

How can I solve this problem without put my server addres on spring annotation on controller:

Controller.java

@CrossOrigin(origins = "http://localhost:8233/", maxAge = 3600)
@RestController
@RequestMapping("/access-type")
@Validated
public class AccessTypeController {

Why the error occurs only on OPTIONS method?

CodePudding user response:

in your .htaccess:

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

and if needed

Header add Access-Control-Allow-Credentials "true"

Don't forget to activate the apache module headers a2enmod headers

CodePudding user response:

You need to specify what to do with CORS, which is what you've done with @CrossOrigin. There's no way out of this (other than setting a wildcard like *)

You can inject an application variable with the host name, however then you need to do the same with every controller. It's easier to set a CORS config bean

On recent versions of Spring Boot, you can create a CorsConfigurationBean like this (in any @Configuration annotated class`:

    /**
     * specify CORS to work from SPA UI
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(List.of("http://localhost:300*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

Read the docs for deatils of this specific config (ie allow credentials is to send headers that mean the browser will send cookies ) Spring CORS Docs

Its pretty simple to set the allowed origin in the application.properties file and you can use profiles to set it for the relevant environment.

I dont think the proxy should affect anything, however I would remove the CORS headers from that configuration (Access-Allow-*) as it will only serve to confuse what's happening between the server and the client.

  • Related