How to resolve CORS issue without using Spring Security

Viewed 731

I have this WebMvcConfigurer which works totally fine when deployed over the server. But when I try to send a request from my locally served Angular project to the server, I get the following error.

Access to XMLHttpRequest at 'https://sub.domain.com/api/staff/logout' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

My Config is as follows:

@Configuration
@EnableWebMvc
public class WebMvcConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS").allowedOrigins("*")
                        .allowedHeaders("*")
                        .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
                        .allowCredentials(true).maxAge(3600);
            }

            /**
             * To add our interceptor into Spring configuration, we need to override
             * addInterceptors() method WebMvcConfig class that implements WebMvcConfigurer.
             */
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(new AppInterceptor());
            }
        };
    }
}

I have referred to other questions my didn't find anything that solved my problem. Thanks in advance.

2 Answers

In your Angular application you can add a proxy.config.json that will solve the CORS issue for you locally. This configuration only affects when serving the app locally, so nothing will change on production.

{
    "/api/*": {
      "target": "http://localhost:8080",
      "secure": false,
      "logLevel": "debug",
      "changeOrigin": false
    }
}

Also, see this answer: https://stackoverflow.com/a/47537203/9698467 and the Angular documentation: https://angular.io/guide/build#proxying-to-a-backend-server

The idea is that even though the front-end and the back-end are served on localhost, there is a local server that serves the Angular app and a local server that serves your backend. They are both served on different ports, which causes a cross-origin issue. By using proxy you are effectively routing your Angular backend requests to localhost:8080, thus from Angular's client point of view, everything seems to be on the same origin.

As I'll be implementing Spring Security in the future, and though the question says without Spring Security, I solved this issue by adding Spring Security to the project,

The starter dependency:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

The Configuration Class:

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;

import java.util.List;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(
                List.of("Authorization", "Cache-Control", "Content-Type", "X-PT-SESSION-ID", "NGSW-BYPASS"));
        corsConfiguration.setAllowedOrigins(List.of("*"));
        corsConfiguration
                .setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT", "OPTIONS", "PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));

        http.authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated().and().csrf().disable()
                .cors().configurationSource(request -> corsConfiguration);

    }
}

I referred this answer, and there are other answers that might be helpful to others as well. Do check it out.

Related