0

I'm having problems with the authentication route using spring cloud gateway with oauth.I have 3 simple authentication services, which have a gateway, an oauth configuration service and the user. When I make the request using the /ms_oauth/oauth2/token route, I receive a 404 error and cannot find the solution.

{
    "timestamp": "2024-06-16T17:16:42.545+00:00",
    "path": "/ms_oauth/oauth2/token",
    "status": 404,
    "error": "Not Found",
    "requestId": "4cb0306d"
}

Pattern "[/users/**]" does not match against value "/ms_oauth/oauth2/token"
2024-06-16T14:29:32.173-03:00 TRACE 6552 --- [ms_gateway] [     parallel-1] o.s.c.g.h.p.PathRoutePredicateFactory    : Pattern "[/oauth2/**]" does not match against value "/ms_oauth/oauth2/token"
2024-06-16T14:29:32.173-03:00 TRACE 6552 --- [ms_gateway] [     parallel-1] o.s.c.g.h.RoutePredicateHandlerMapping   : No RouteDefinition found for [Exchange: POST http://localhost:8001/ms_oauth/oauth2/token]

application.properties - GATEWAY

eureka.client.service-url.defaultZone = http://localhost:8761/eureka
spring.application.name=ms_gateway
server.port=8001

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

spring.main.web-application-type=reactive
spring.main.allow-bean-definition-overriding=true
#security.oauth2.resource.filter-order=3

spring.cloud.discovery.enabled=true

spring.cloud.gateway.routes[0].id=ms_user
spring.cloud.gateway.routes[0].uri=lb://ms_user
spring.cloud.gateway.routes[0].predicates=Path=/users/**

spring.cloud.gateway.routes[1].id=ms_oauth
spring.cloud.gateway.routes[1].uri=lb://ms_oauth
spring.cloud.gateway.routes[1].predicates=Path=/oauth2/**
spring.cloud.gateway.routes[1].filters[0].name=RewriteResponseHeader
spring.cloud.gateway.routes[1].filters[0].args.name=Set-Cookie
spring.cloud.gateway.routes[1].filters[0].args.regexp=.*
spring.cloud.gateway.routes[1].filters[0].args.replacement=secure-cookie=value; Secure

application.properties - OAUTH

spring.application.name=ms_oauth

security.client-id=${CLIENT_ID:clientid}
security.client-secret=${CLIENT_SECRET:clientsecret}
security.jwt.duration=${JWT_DURATION:86400}

eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${random.value}}
eureka.client.service-url.defaultZone = http://localhost:8761/eureka
server.port=${PORT:8002}

In the gateway api I have the following authentication rule:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@EnableWebFluxSecurity
public class ResourceServerConfig {

    @Value("${cors.origins}")
    private String corsOrigins;

    @Bean
    @Profile("test")
    @Order(1)
    public SecurityFilterChain h2SecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(PathRequest.toH2Console()).csrf(AbstractHttpConfigurer::disable)
                .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable));
        return http.build();
    }

    @Bean
    @Order(3)
    public SecurityFilterChain rsSecurityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable);
        http.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll());
        http.oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer.jwt(Customizer.withDefaults()));
        http.cors(cors -> cors.configurationSource(corsConfigurationSource()));
        return http.build();
    }

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
        grantedAuthoritiesConverter.setAuthorityPrefix("");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }

//  @Bean
//  public JwtDecoder jwtDecoder() {
//      return NimbusJwtDecoder.withJwkSetUri("https://myapp.auth0.com/.well-known/jwks.json").build();
//  }
    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .csrf(ServerHttpSecurity.CsrfSpec::disable);
        return http.build();
    }
    @Bean
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }

    @Bean
    public JWKSource<SecurityContext> jwkSource() {
        RSAKey rsaKey = generateRsa();
        JWKSet jwkSet = new JWKSet(rsaKey);
        return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
    }

    private static RSAKey generateRsa() {
        KeyPair keyPair = generateRsaKey();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();
    }

    private static KeyPair generateRsaKey() {
        KeyPair keyPair;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        return keyPair;
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {

        String[] origins = corsOrigins.split(",");

        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowedOriginPatterns(Arrays.asList(origins));
        corsConfig.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "DELETE", "PATCH"));
        corsConfig.setAllowCredentials(true);
        corsConfig.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));

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

    @Bean
    FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(
                new CorsFilter(corsConfigurationSource()));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

The 3 services are registered and running normally on EUREKA CLIENT.

I tried changing the routes and removed the @EnableWebFluxSecurity annotation but I get the csrf disabled error.

2
  • 404 means NOT FOUND, meaning in case of gateway that the route is not matched - most likely because your predicate matches /oauth2/** and not /ms_oauth/oauth2/**
    – J Asgarov
    Commented Jun 16 at 20:12
  • No RouteDefinition found for [Exchange: POST localhost:8001/ms-oauth/oauth2/token] Commented Jun 17 at 12:09

0