CORS error when calling endpoint from my Angular SPA

Discussão em 'Angular' iniciado por ousmane MBINTE, Abril 14, 2025.

  1. I have a Spring boot microservice application using Spring Cloud Gateway for exposing microservices to frontend. When I try to call them from my Angular 19 SPA I get a CORS error despite having activated configuration to add Access-Control-Allow-Origin in header. I activated the HttpOnly for delegate the token handeling at backend. When I call login, register or logout endpoint everything works well, but In the header of my application I have a service to get connected user informations, and the calling of this service in onInit getting a 401. You can find bellow configuration files.

    dashboard:1 Access to XMLHttpRequest at 'http://localhost:8084/api/1.0/users/8aad4849-21eb-4fc1-b852-83e078c2a90e' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    user-account.service.ts:21 Account API error HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: 'Unknown Error', url: 'http://localhost:8084/api/1.0/users/8aad4849-21eb-4fc1-b852-83e078c2a90e', ok: false, …}error: ProgressEvent {isTrusted: true, lengthComputable: false, loaded: 0, total: 0, type: 'error', …}headers: HttpHeaders {headers: Map(0), normalizedNames: Map(0), lazyInit: undefined, lazyUpdate: null}message: "Http failure response for http://localhost:8084/api/1.0/users/8aad4849-21eb-4fc1-b852-83e078c2a90e: 0 Unknown Error"name: "HttpErrorResponse"ok: falsestatus: 0statusText: "Unknown Error"type: undefinedurl: "http://localhost:8084/api/1.0/users/8aad4849-21eb-4fc1-b852-83e078c2a90e"[[Prototype]]: HttpResponseBase


    Api gateway configuration

    spring:
    application:
    name: api-gateway
    cloud:
    gateway:
    routes:
    - id: auth-service
    uri: lb://auth-service
    predicates:
    - Path=/api/1.0/auth/**
    - id: account-service
    uri: lb://account-service
    predicates:
    - Path=/api/1.0/users/**
    globalcors:
    corsConfigurations:
    '[/**]':
    allowedOrigins:
    - "http://localhost:4200"
    allowedMethods:
    - GET
    - POST
    - PUT
    - DELETE
    - OPTIONS
    allowedHeaders:
    - "*"
    allowCredentials: true
    security:
    oauth2:
    resourceserver:
    jwt:
    issuer-uri: http://localhost:8080/realms/My-Realm_Realm
    server:
    port: 8084
    error:
    include-stacktrace: always
    eureka:
    client:
    serviceUrl:
    defaultZone: http://localhost:8761/eureka/
    instance:
    prefer-ip-address: true


    Security Configuration

    package com.omb.ombgateway.configuration;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.Customizer;
    import org.springframework.security.config.web.server.ServerHttpSecurity;
    import org.springframework.security.web.server.SecurityWebFilterChain;
    import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;

    @Configuration
    public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain gatewaySecurity(ServerHttpSecurity http) throws Exception {
    http
    .csrf(csrf -> csrf.disable())
    .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
    .authorizeExchange(exchanges -> exchanges
    .pathMatchers("/api/1.0/auth/**", "/actuator/**", "/error").permitAll()
    .anyExchange().authenticated()
    )
    .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
    }
    }


    Accout microservice security config

    package com.omb.ombaccount.configuration;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.Customizer;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
    import org.springframework.security.web.SecurityFilterChain;

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new KeycloakRoleConverter());

    http
    .csrf(csrf -> csrf.disable())
    .cors(Customizer.withDefaults())
    .authorizeHttpRequests(auth -> auth
    .requestMatchers("/api/**").hasAnyRole("USER", "ADMIN")
    .requestMatchers("/actuator/**", "/h2-console/**").permitAll()
    )
    .oauth2ResourceServer(oauth2 -> oauth2
    .jwt(jwt -> jwt
    .jwtAuthenticationConverter(jwtAuthenticationConverter)
    )
    );
    return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder(16);
    }
    }


    Account CORS configuration

    package com.omb.ombaccount.configuration;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.reactive.CorsWebFilter;
    import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

    @Configuration
    public class CorsGlobalConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter() {
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.setAllowCredentials(true);
    corsConfig.addAllowedOrigin("http://localhost:4200");
    corsConfig.addAllowedHeader("*");
    corsConfig.addAllowedMethod("GET");
    corsConfig.addAllowedMethod("POST");
    corsConfig.addAllowedMethod("PUT");
    corsConfig.addAllowedMethod("DELETE");
    corsConfig.addAllowedMethod("OPTIONS");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);

    return new CorsWebFilter(source);
    }
    }


    account http client

    getUserAccount(id: string): Observable<UserAccountModel> {
    return this.http.get<UserAccountModel>(this.accountBaseUrl + '/'+id, { withCredentials: true }).pipe(
    catchError(error => {
    console.error('Account API error', error);
    return throwError(() => error);
    })
    );
    }

    Continue reading...

Compartilhe esta Página