# EnableReactiveMethodSecurity Spring Security supports method security using [Reactor’s Context](https://projectreactor.io/docs/core/release/reference/#context) which is setup using `ReactiveSecurityContextHolder`. For example, this demonstrates how to retrieve the currently logged in user’s message. | |For this to work the return type of the method must be a `org.reactivestreams.Publisher` (i.e. `Mono`/`Flux`) or the function must be a Kotlin coroutine function.
This is necessary to integrate with Reactor’s `Context`.| |---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Java ``` Authentication authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER"); Mono messageByUsername = ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .map(Authentication::getName) .flatMap(this::findMessageByUsername) // In a WebFlux application the `subscriberContext` is automatically setup using `ReactorContextWebFilter` .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)); StepVerifier.create(messageByUsername) .expectNext("Hi user") .verifyComplete(); ``` Kotlin ``` val authentication: Authentication = TestingAuthenticationToken("user", "password", "ROLE_USER") val messageByUsername: Mono = ReactiveSecurityContextHolder.getContext() .map(SecurityContext::getAuthentication) .map(Authentication::getName) .flatMap(this::findMessageByUsername) // In a WebFlux application the `subscriberContext` is automatically setup using `ReactorContextWebFilter` .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication)) StepVerifier.create(messageByUsername) .expectNext("Hi user") .verifyComplete() ``` with `this::findMessageByUsername` defined as: Java ``` Mono findMessageByUsername(String username) { return Mono.just("Hi " + username); } ``` Kotlin ``` fun findMessageByUsername(username: String): Mono { return Mono.just("Hi $username") } ``` Below is a minimal method security configuration when using method security in reactive applications. Java ``` @EnableReactiveMethodSecurity public class SecurityConfig { @Bean public MapReactiveUserDetailsService userDetailsService() { User.UserBuilder userBuilder = User.withDefaultPasswordEncoder(); UserDetails rob = userBuilder.username("rob") .password("rob") .roles("USER") .build(); UserDetails admin = userBuilder.username("admin") .password("admin") .roles("USER","ADMIN") .build(); return new MapReactiveUserDetailsService(rob, admin); } } ``` Kotlin ``` @EnableReactiveMethodSecurity class SecurityConfig { @Bean fun userDetailsService(): MapReactiveUserDetailsService { val userBuilder: User.UserBuilder = User.withDefaultPasswordEncoder() val rob = userBuilder.username("rob") .password("rob") .roles("USER") .build() val admin = userBuilder.username("admin") .password("admin") .roles("USER", "ADMIN") .build() return MapReactiveUserDetailsService(rob, admin) } } ``` Consider the following class: Java ``` @Component public class HelloWorldMessageService { @PreAuthorize("hasRole('ADMIN')") public Mono findMessage() { return Mono.just("Hello World!"); } } ``` Kotlin ``` @Component class HelloWorldMessageService { @PreAuthorize("hasRole('ADMIN')") fun findMessage(): Mono { return Mono.just("Hello World!") } } ``` Or, the following class using Kotlin coroutines: Kotlin ``` @Component class HelloWorldMessageService { @PreAuthorize("hasRole('ADMIN')") suspend fun findMessage(): String { delay(10) return "Hello World!" } } ``` Combined with our configuration above, `@PreAuthorize("hasRole('ADMIN')")` will ensure that `findByMessage` is only invoked by a user with the role `ADMIN`. It is important to note that any of the expressions in standard method security work for `@EnableReactiveMethodSecurity`. However, at this time we only support return type of `Boolean` or `boolean` of the expression. This means that the expression must not block. When integrating with [WebFlux Security](../configuration/webflux.html#jc-webflux), the Reactor Context is automatically established by Spring Security according to the authenticated user. Java ``` @EnableWebFluxSecurity @EnableReactiveMethodSecurity public class SecurityConfig { @Bean SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception { return http // Demonstrate that method security works // Best practice to use both for defense in depth .authorizeExchange(exchanges -> exchanges .anyExchange().permitAll() ) .httpBasic(withDefaults()) .build(); } @Bean MapReactiveUserDetailsService userDetailsService() { User.UserBuilder userBuilder = User.withDefaultPasswordEncoder(); UserDetails rob = userBuilder.username("rob") .password("rob") .roles("USER") .build(); UserDetails admin = userBuilder.username("admin") .password("admin") .roles("USER","ADMIN") .build(); return new MapReactiveUserDetailsService(rob, admin); } } ``` Kotlin ``` @EnableWebFluxSecurity @EnableReactiveMethodSecurity class SecurityConfig { @Bean open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { return http { authorizeExchange { authorize(anyExchange, permitAll) } httpBasic { } } } @Bean fun userDetailsService(): MapReactiveUserDetailsService { val userBuilder: User.UserBuilder = User.withDefaultPasswordEncoder() val rob = userBuilder.username("rob") .password("rob") .roles("USER") .build() val admin = userBuilder.username("admin") .password("admin") .roles("USER", "ADMIN") .build() return MapReactiveUserDetailsService(rob, admin) } } ```