spring-webflux-security-jwt
spring-webflux-security-jwt copied to clipboard
Split responsibility of ServerHttpBearerAuthenticationConverter
I think ServerHttpBearerAuthenticationConverter should be used only for preparing the token for further processing:
Mono.justOrEmpty(serverWebExchange)
.map(JWTAuthorizationPayload::extract)
while authenticating the token:
map(VerifySignedJWT::check)
.map(UsernamePasswordAuthenticationFromJWTToken::create)
is the responsibility of JWTReactiveAuthenticationManager
By the way - instead of providing own implementation of JWTAuthorizationWebFilter just do:
@Component
public class JWTAuthenticationWebFilter extends AuthenticationWebFilter {
public JWTAuthenticationWebFilter(final JWTAuthenticationManager authenticationManager,
final ServerHttpBearerAuthenticationConverter converter,
final UnauthorizedAuthenticationEntryPoint entryPoint) {
super(authenticationManager);
setAuthenticationConverter(converter);
setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(entryPoint));
setRequiresAuthenticationMatcher(new JWTHeadersExchangeMatcher()); //this is necessary to match headers. Requests without JWT header should not be taken into account by this filter
}
private static class JWTHeadersExchangeMatcher implements ServerWebExchangeMatcher {
@Override
public Mono<MatchResult> matches(final ServerWebExchange exchange) {
return Mono.just(exchange)
.map(ServerWebExchange::getRequest)
.map(ServerHttpRequest::getHeaders)
.filter(h -> h.containsKey("some JWT header"))
.flatMap($ -> MatchResult.match())
.switchIfEmpty(MatchResult.notMatch());
}
}
}
And don't forget to set:
http
.exceptionHandling()
.authenticationEntryPoint(new UnauthorizedAuthenticationEntryPoint ())
.and()
where
@Component
public class UnauthorizedAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
@Override
public Mono<Void> commence(final ServerWebExchange exchange, final AuthenticationException e) {
return Mono.fromRunnable(() -> exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED));
}
}
otherwise SpringSecurity will still display BasicAuth on requests without headers
🤔 thank you for your suggestion. I will go through this and see what I can do