Reputation: 31
I have a problem with my spring boot application (version 2.6.3). I have configured reactive spring security like there:
MyApplication.java:
@SpringBootApplication
@EnableWebFlux
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class);
}
@Bean
public SecurityWebFilterChain springSecurityFilterChain(final ServerHttpSecurity http, final ReactiveOpaqueTokenIntrospector reactiveOpaqueTokenIntrospector) {
return http.authorizeExchange()
.anyExchange().authenticated()
.and()
.httpBasic().disable()
.cors().and()
.logout().disable()
.formLogin().disable()
.oauth2ResourceServer()
.opaqueToken()
.introspector(reactiveOpaqueTokenIntrospector)
.and().and()
.csrf()
.disable()
.build();
}
}
And this is my web resource (controller):
MyWebResource.java:
@RestController
public class MyWebResource implements MyWebResourceApi {
@PreAuthorize("hasRole('ROLE_USER')")
@Override
public Mono<String> details(String userId, ServerWebExchange exchange) {
return exchange.getPrincipal().map(Principal::getName);
}
}
It's work fine, when my access token is expired or incorrect the request should be denied. However when PreAuthorized allow request, my user principal will be never resolved in my exchange...
Upvotes: 2
Views: 8164
Reputation: 13051
I found this answer looking for a way to add the access token to my webclient requests. If we are using OAuth2 or OpenID Connect and want to access the token instead of the principal's name, then this is not possible via the principal in the security context.
Instead we need to create a ServerOAuth2AuthorizedClientExchangeFilterFunction
and register it as a filter function to the WebClient:
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations,
authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
where clientRegistrations
is an injectabile bean of type ReactiveClientRegistrationRepository
and authorizedClients
is an injectable bean of type ServerOAuth2AuthorizedClientRepository
.
We can then use the filters
method for the builder to add our filter function to the exchangeFilterFunctions
:
WebClient.builder()
.filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(oauth);
})
.build();
Baeldung has a nice background article about this, which explains it in more detail: https://www.baeldung.com/spring-webclient-oauth2
Upvotes: 1
Reputation: 5924
In reactive application authentication information is stored in the Reactive flow and accessible from Mono
/Flux
. You could use ReactiveSecurityContextHolder
to obtain the currently authenticated principal, or an authentication request token.
@PreAuthorize("hasRole('ROLE_USER')")
public Mono<String> details() {
return ReactiveSecurityContextHolder.getContext()
.map(ctx -> ((Principal) ctx.getAuthentication().getPrincipal()).getName());
}
Upvotes: 7