Spring MVC has a lot of sensible defaults that are lacking in WebFlux. This is one of them.
I worked around this issue by setting up a WebFilter that takes tokens in the query string and add them to the header.
@Override
@NonNull
public Mono<Void> filter(
@NonNull ServerWebExchange serverWebExchange, @NonNull WebFilterChain
webFilterChain) {
ServerHttpRequest request = serverWebExchange.getRequest();
return webFilterChain.filter(
serverWebExchange.mutate().request(sanitizeRequest(request)).build());
}
private ServerHttpRequest sanitizeRequest(ServerHttpRequest request) {
MultiValueMap<String, String> queryParams = request.getQueryParams();
ServerHttpRequest.Builder newRequest =
request
.mutate()
.headers(
headers -> {
if (headerContainsAuthorizationKey(headers)) {
String token = getAuthorizationBearer(headers);
if (token != null) {
// "bearer" breaks WebFlux OAuth :)
headers.set(HttpHeaders.AUTHORIZATION, token.replace("bearer", "Bearer"));
return;
}
}
if (pathContainsAccessToken(queryParams)) {
headers.set(
HttpHeaders.AUTHORIZATION,
"Bearer " + queryParams.getFirst("access_token"));
}
});
if (pathContainsAccessToken(queryParams)) {
newRequest.uri(buildNewUriWithoutToken(request.getURI(), queryParams));
}
return newRequest.build();
}
}
It's nice pointing out that the lowercase "bearer" breaks WebFlux as well.
After that, you can add this filter right before your oauthResourceServer spec in the security chain:
@Bean
public SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http,
TokenStore tokenStore,
AuthorizationHeaderFilter authorizationHeaderFilter) {
http.csrf()
.disable()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.addFilterAt(authorizationHeaderFilter, SecurityWebFiltersOrder.FIRST)
.oauth2ResourceServer()
.jwt() // ... etc
return http.build();
}