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.
/oauth2/**
and not/ms_oauth/oauth2/**