CORS Missing Allow Oirign with angular, spring webflux and spring oauth2 client

177 Views Asked by At

I want to create a simple webapp based on Angular. That is able to retrieve data from the with oauth secured battlenet resource server.

My planned structure is like.

  • Angular
  • Spring boot as oauth2 client using spring webflux
  • Battlenet authentication + resource server

I was able to setup my spring boot app, that I'm able to retrieve data by direct endpoint calls via browser.

If I try to do the same via angular app, I'm getting cross origin errors while oauth authentication.

Browser info from inspect -> network

My configuration

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain configure(ServerHttpSecurity http) {
        return http.cors(cors -> cors.configurationSource(corsConfigurationSource()))
                    .authorizeExchange(auth -> auth.anyExchange().authenticated())
                    .oauth2Login(withDefaults())
                    .build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("http://localhost:4200"));
        configuration.setAllowedMethods(List.of("*"));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setMaxAge(3600L);
        configuration.applyPermitDefaultValues();

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo,
                               ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction filter =
                new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                        clientRegistrationRepo,
                        authorizedClientRepo);
        return WebClient.builder()
                .baseUrl("https://eu.api.blizzard.com")
                .filter(filter)
                .build();
    }

}

My rest controller

@RestController
public class UserController {

    @GetMapping("/user")
    public Mono<String> getUserName(@AuthenticationPrincipal Mono<OAuth2User> oauth2User) {
        return oauth2User
                .mapNotNull(OAuth2User::getName)
                .map(name -> String.format("Hi, %s", name));
    }

}

My Angular App Demo call

  sendRequest() {
    const headers= new HttpHeaders()
      .set('Access-Control-Allow-Origin', 'http://localhost:4200');

    const requestOptions = { headers: headers };

    this.http.get('http://localhost:8080/user')
              .subscribe(response => this.apiResponse = response);
  }

Please, help me to solve this cors issue.

1

There are 1 best solutions below

2
ch4mp On

Your CORS error is on a request to battle.net. It can't be fixed with the configuration of your Angular or Spring applications.

Instead of following redirects to battle.net within your app:

  • temporarily "quit" your Angular app by setting the window.location.href to the battle.net authorization endpoint. That way origin will be battle.net (and not your Angular app)
  • be sure to use a redirect_uri pointing to your Spring app authorization-code endpoint (http://127.0.0.1:8080/login/oauth2/code/your-registration-id)
  • in Spring OAuth2 client, configure a success URL to return to your Angular app (http://localhost:4200/, unless your Spring client is a spring-cloud-gateway also proxying your Angular app with route like http://localhost:8080/ui)

I have written a tutorial with an Angular app querying a Spring reactive OAuth2 client (a spring-cloud-gateway instance). You can see how login is initiated in the Angular app there.