Im using webflux in my program and oauth2 security (keycloack as UAA server
) I want to extract some information from oauth2 jwt and I do it well . but i need to get some information in filter .
when I use my old method it not work in filter (WebFilter
) .
Is there any way to parse token and get information from it ?
Is my way correct or I should extract it using springSecurityFilterChain
instead of WebFilter?
I want check accountId in token with accountId in url that client send using filter.
Hear is my code to extract accountId it not work in WebFilter but it work when i use it services or controller
public class SecurityFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication).map(Principal::getName).filter((accountId) -> accountId.equals(clientAccountId)
.switchIfEmpty(Mono.error(new SystemException("401 ERROR")));;
return webFilterChain.filter(serverWebExchange);
}
Hear is my second way to extract accountId :
public class SecurityFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
serverWebExchange.getPrincipal().map(Principal::getName).filter((accountId) -> accountId.equals(clientAccountId). .switchIfEmpty(Mono.error(new SystemException("401 ERROR")));;
return webFilterChain.filter(serverWebExchange);
}
and my security config is :
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/api/**").authenticated()
// .pathMatchers("/**").permitAll()
.anyExchange().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(new HttpStatusServerAccessDeniedHandler(HttpStatus.BAD_REQUEST))
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(grantedAuthoritiesExtractor());
return http.build();
}
I think i should have another SecurityWebFilterChain
method that do this for me ??
You are looking for smth like this
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
var clientAccountId = "clientId";
return exchange.getPrincipal()
.map(Principal::getName)
.flatMap((accountId) -> {
if (accountId.equals(clientAccountId) && exchange.getRequest().getPath().value().equals("/my/api")) {
return Mono.just(accountId);
}
return Mono.error(new IllegalArgumentException("401 ERROR"));
})
.flatMap(tokenJwt -> chain.filter(exchange))
.onErrorResume(r -> {
exchange.getResponse().setRawStatusCode(HttpStatus.UNAUTHORIZED.value());
return exchange.getResponse().setComplete();
});
}
Note: that when you are using reactive then until you or spring subscribe to it it wont be executed.