1

I'm trying to use spring cloud gateway with spring security and trying to call the rest API through angular but I'm getting following error

Access to XMLHttpRequest at 'http://localhost:9090/api/v1/publishers/?pageNo=1&pageSize=10&sort=name,desc&sort=city,desc' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

According to the documentation https://cloud.spring.io/spring-cloud-gateway/multi/multi__cors_configuration.html

I have to add globalcors in application yaml file.

here is my complete yaml file.

server:
  port: 9090
keycloak-client:
  server-url: http://keycloak-url:8080/auth
  realm: dev
spring:
  application:
    name: gateway
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${keycloak-client.server-url}/realms/${keycloak-client.realm}
            user-name-attribute: preferred_username
        registration:
          keycloak:
            client-id: cei-backend
            client-secret: f4d3242b-1fee-4dab-a491-d91ac51d637f
  cloud:
    gateway:
      default-filters:
        - TokenRelay
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "http://localhost:4200"
            allowedHeaders: "*"
            allowedMethods:
            - GET
            - POST
            - DELETE
            - PUT
      routes:
        - id: publisher_route
          uri: http://localhost:8000
          predicates:
            - Path=/api/v1/publishers/**
          filters:
            - RemoveRequestHeader=Cookie        
logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    reactor.netty: DEBUG

Following is my security config file

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
                                                            ReactiveClientRegistrationRepository clientRegistrationRepository) {
        // Authenticate through configured OpenID Provider
        http.oauth2Login();
        // Also logout at the OpenID Connect provider
        http.logout(logout -> logout.logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler(
                clientRegistrationRepository)));
        // Require authentication for all requests
        http.authorizeExchange().anyExchange().authenticated();
        // Allow showing /home within a frame
        http.headers().frameOptions().mode(Mode.SAMEORIGIN);
        // Disable CSRF in the gateway to prevent conflicts with proxied service CSRF
        http.csrf().disable();

        return http.build();
    }

I'm calling this API from angular but I'm getting CORS error on the preflight request. I have tried everything but no idea where I'm making a mistake. Any idea?

user585014
  • 157
  • 5
  • 14
  • 1
    It looks like your preflight request is redirected and not processed correctly (you should to add preflight request/response to the question to be clear). I guess it's because you require authentication for all requests. I would say that OPTIONS requests should be whitelisted somehow. – Jan Garaj Apr 25 '21 at 14:43
  • Does this answer your question? [How to resolve 'preflight is invalid (redirect)' or 'redirect is not allowed for a preflight request'](https://stackoverflow.com/questions/42168773/how-to-resolve-preflight-is-invalid-redirect-or-redirect-is-not-allowed-for) – Jan Garaj Apr 25 '21 at 14:43
  • Hi @JanGaraj I solved it by moving the angular app behind the API Gateway. Thanks – user585014 Apr 26 '21 at 16:08
  • @user585014 How did you move Angular behind the API Gateway? Do you have git about your project? – Braian Silva May 14 '21 at 19:09
  • Simply add a new route in your API routes - id: frontend_route uri: http://localhost:4200 predicates: - Path=/** filters: - RemoveRequestHeader=Cookie and then add following in your security config .pathMatchers("/portal/**").permitAll() – user585014 May 15 '21 at 23:48

2 Answers2

0

I solved it by moving Angular App behind the API gateway and added the following code in the API Gateway and Microservice

In API Gateway

http.cors();

In Microservice

@Configuration
@EnableWebMvc
public class RestServiceCorsApplication implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}
user585014
  • 157
  • 5
  • 14
0

Add HttpMethod.OPTIONS to your Allowed Methods. Preflight requests to the server are sent using the OPTIONS method. So your config should look like the one below:

allowedMethods:
        - GET
        - POST
        - DELETE
        - PUT
        - OPTIONS

In addition your routes must include the OPTIONS method. e.g.:

spring.cloud.gateway.routes[0].predicates[1] = Method=GET,POST,OPTIONS
Lukuluba
  • 381
  • 1
  • 5
  • 18