I've configured auth0 authentication with spring cloud API gateway, My basic setup is as follows,
POST - /user/api/user/registration - PermitAll
All Other API endpoints are authenticated.
So used the following SecurityConfiguration with the spring boot application,
package com.app.source.configuration.security;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
//ALLOW USER REGISTRATION API WITHOUT AUTHENTICATION
.pathMatchers("/user/api/v1/user/registration").permitAll()
//ALL OTHER APIS ARE AUTHENTICATED
.anyExchange().authenticated()
.and()
.csrf().disable()
.oauth2Login()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
The authentication layer has applied to the necessary API endpoints and it's working as I need, But this registration endpoint sends empty 200 Response, But It's not getting through the API gateway. But the same API works when sending it with an authentication header. I'm attaching DEBUG logs I've got with the API gateway.
API that needs to have an authentication token, which works correctly and sends 401 on unauthorized requests.
API that was configured open which sends 200 from API gateway without going through,
The same API works well when I've attached the auth token, which is not acceptable behavior.
Request with valid auth token
2022-05-14 02:26:29.918 DEBUG 9999 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [1f1cee98-10, L:/0:0:0:0:0:0:0:1:8082 - R:/0:0:0:0:0:0:0:1:61057] HTTP POST "/user/api/v1/user/registration"
2022-05-14 02:26:29.934 DEBUG 9999 --- [oundedElastic-3]
o.s.w.s.s.DefaultWebSessionManager : Created new WebSession.
2022-05-14 02:26:32.497 DEBUG 9999 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [1f1cee98-10, L:/0:0:0:0:0:0:0:1:8082 - R:/0:0:0:0:0:0:0:1:61057] Completed 200 OK
-----------
Request without token which is returning 200 in the same second without processing it.
2022-05-14 02:26:45.950 DEBUG 9999 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [1f1cee98-11, L:/0:0:0:0:0:0:0:1:8082 - R:/0:0:0:0:0:0:0:1:61057] HTTP POST "/user/api/v1/user/registration"
2022-05-14 02:26:45.960 DEBUG 9999 --- [oundedElastic-3] o.s.w.s.s.DefaultWebSessionManager : Created new WebSession.
2022-05-14 02:26:45.977 DEBUG 9999 --- [oundedElastic-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [1f1cee98-11, L:/0:0:0:0:0:0:0:1:8082 - R:/0:0:0:0:0:0:0:1:61057] Completed 200 OK
CodePudding user response:
The problem is in the filter
@Bean
public GlobalFilter customGlobalFilter() {
return ((exchange, chain) -> exchange.getPrincipal().map(principal -> {
String userName = "";
if (principal instanceof JwtAuthenticationToken) {
//Get username from Principal
userName = principal.getName();
}
// adds header to proxied request
exchange.getRequest().mutate()
.header("X-Auth-Id", userName)
.build();
return exchange;
}).flatMap(chain::filter).then(Mono.fromRunnable(() -> {
})));
}
if you deleted works just fine
CodePudding user response:
The original issue was with custom filter that written to capture incoming request principal username, Added defaultIfEmpty and allowed unauthorized user request.
package com.app.configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import java.security.Principal;
@Slf4j
@Configuration
public class GatewayConfiguration {
private static final String HTTP_HEADER_AUTH_USER_ID = "X-Auth-Id";
private static final String UNAUTHORIZED_USER_NAME = "SYSTEM USER";
@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> exchange.getPrincipal().map(Principal::getName).defaultIfEmpty(UNAUTHORIZED_USER_NAME).map(principal -> {
// adds header to proxied request
exchange.getRequest().mutate()
.header(HTTP_HEADER_AUTH_USER_ID, principal)
.build();
return exchange;
}).flatMap(chain::filter).then(Mono.fromRunnable(() -> {
}));
}
}