springangularspring-boot

Springboot endpoint 403 OPTIONS when doing a POST request


I'm running a service using Spring and my Angular front-end is getting a 403 with Request Method: OPTIONS when it tries to make a POST request.

Both the Spring service and the Angular app are running locally on my machine. I tried toggling CORS with a Chrome plugin, but that didn't seem to fix the issue.

All my GET requests to the service seem to work alright. I can do the POST request in Postman, so I'm not sure why the angular app can't make the request, but Postman can.

****EDIT****

Response Headers

Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
Content-Length: 20
Date: Sat, 31 Mar 2018 19:15:01 GMT

Request Headers

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:9901
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36

Solution

  • CORS Request is made by your Frontend to see what are the methods (HTTP Verbs) that your backed allows. This is usually required for monetary operations e.g., POST or PUT which are meant to modify data.

    Hence your Frontend will make this call first and your backend needs to respond with allowed methods, you can also restrict specific URIs, then upon successful validation, the target call is made.

    This is perfectly normal and angular does this internally so as to not make an unnecessary data request without knowing whether the server will allow.

    Here's how you will set it up in Spring.

        //Change/Customize as necessary
        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.addAllowedOrigin("<your origin>");
            corsConfiguration.setAllowedMethods(Arrays.asList(
                    HttpMethod.GET.name(),
                    HttpMethod.HEAD.name(),
                    HttpMethod.POST.name(),
                    HttpMethod.PUT.name(),
                    HttpMethod.DELETE.name()));
            corsConfiguration.setMaxAge(1800L);
            source.registerCorsConfiguration("/**", corsConfiguration); // you restrict your path here
            return source;
        }
    

    If you are also using any custom response headers from your backend, then you need to allow that as well in the CORS configuration. As an example

        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addExposedHeader("header1");
        corsConfiguration.addExposedHeader("header2");