# 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.<br/>This is necessary to integrate with Reactor’s `Context`.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

Java

```
Authentication authentication = new TestingAuthenticationToken("user", "password", "ROLE_USER");

Mono<String> 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<String> = 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<String> findMessageByUsername(String username) {
	return Mono.just("Hi " + username);
}
```

Kotlin

```
fun findMessageByUsername(username: String): Mono<String> {
	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<String> findMessage() {
		return Mono.just("Hello World!");
	}
}
```

Kotlin

```
@Component
class HelloWorldMessageService {
	@PreAuthorize("hasRole('ADMIN')")
	fun findMessage(): Mono<String> {
		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)
	}
}
```