3

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...

1
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Mar 20, 2022 at 6:33

2 Answers 2

8

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()); } 
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.