Search code examples
angularspring-securitymicroserviceskeycloakapi-gateway

Spring Boot Microservice Application Cors Origin Error


Spring Boot 3, Keycloak, Security of Angular Microservice Application API Gateway and Cros Origin, Web Filter are configured when the following error is received?


*Springboot3, Keyclock, Angular Microservice Application When security is configured in the API Gateway in the backend, even if the endpoint is called from the frontend, the cross-origin-allow-header error 401 preflight error is received.

Access to fetch at 'http://localhost:9090/api/v1/programs' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.


[enter link description here][1]
Please give the reason for getting this kind of error even when Cros Origin, web Filter and Keyclock spring.security.oauth2.resourceserver.jwt.issuer-uri application.properties are configured in Api Gateway?
**ApiGateway Configuration Class**
**SecurityConfiguration.Class**
@Configuration
@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http.csrf().disable()
                .authorizeExchange(authorize ->
                        authorize.pathMatchers("/api/v1/users/**").permitAll()
                                .pathMatchers("/eureka/**").permitAll()
                                .anyExchange().authenticated())
                .oauth2ResourceServer(ServerHttpSecurity.OAuth2ResourceServerSpec::jwt);
        return http.build();
    }

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowedOrigins(List.of("*"));
        corsConfig.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        corsConfig.setMaxAge(3600L);
        corsConfig.addAllowedHeader("Content-Type");
        corsConfig.addAllowedHeader("X-Requested-With");
        corsConfig.addAllowedHeader("Authorization");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);
        return new CorsWebFilter(source);
    }
}

**application.properties**
server.port=9090
spring.application.name=api-gateway
spring.cloud.compatibility-verifier.enabled=false
spring.mvc.dispatch-options-request=true

logging.level.root=INFO
logging.level.org.springframework.cloud.gateway.route.RouteDefinitionLocator=INFO
logging.level.org.springframework.cloud.gateway=TRACE

spring.cloud.gateway.routes[0].id=subject-service-api
spring.cloud.gateway.routes[0].uri=lb://subject-service-api
spring.cloud.gateway.routes[0].predicates[0]=Path=/api/v1/subjects/**

spring.cloud.gateway.routes[1].id=program-service-api
spring.cloud.gateway.routes[1].uri=lb://program-service-api
spring.cloud.gateway.routes[1].predicates[0]=Path=/api/v1/programs/**

spring.cloud.gateway.routes[2].id=registration-service-api
spring.cloud.gateway.routes[2].uri=lb://registration-service-api
spring.cloud.gateway.routes[2].predicates[0]=Path=/api/v1/registrations/**

spring.cloud.gateway.routes[3].id=eureka-server-api
spring.cloud.gateway.routes[3].uri=http://localhost:8761
spring.cloud.gateway.routes[3].predicates[0]=Path=/eureka/web
spring.cloud.gateway.routes[3].filters[0]=SetPath=/

spring.cloud.gateway.routes[4].id=eureka-server-api-static-resource
spring.cloud.gateway.routes[4].uri=http://localhost:8761
spring.cloud.gateway.routes[4].predicates[0]=Path=/eureka/**

#eureka configuration
eureka.client.serviceUrl.defaultZone=xxx
#Keycloak security config
spring.security.oauth2.resourceserver.jwt.issuer-uri=xxx

Also, the jwt token is sent from Postman and data is provided when the api endpoint (services) calls services directly from outside the Api Gateway using pathMatchers(" ").permitAll().
Why can't I access services through Api Gateway?

Solution

  • Two possible things to do:

    1. Configure Angular's proxy as described here.

    2. Try setting the header Access-Control-Allow-Origin in the response that Spring Gateway returns to your Angular application like described here. In a more realistic environment you would probably configure your reverse proxy with this header, but it looks like you are testing locally so setting the header in the gateway to * or http://localhost:4200 should work I think.