Summary
When using Spring's security with the Webflux framework, removing and adding users dynamically isn't straightforward.
Actual Behavior
MapReactiveUserDetailsService only has two public methods: find a user by name and update a user's password. These are defined by its two parent interfaces, ReactiveUserDetailsService and ReactiveUserDetailsPasswordService.
Unless you use the MapReactiveUserDetailsService(Map<String, UserDetails> users) constructor and keep a reference to the original map, there is no way to update users dynamically. This workaround seems quite brittle and won't work when using one of the class's two other constructors.
Expected Behavior
MapReactiveUserDetailsService should provide methods to conveniently add and remove users at any point in time. Should these methods be defined in the ReactiveUserDetailsService interface itself?
Version
Latest 5.2.1.RELEASE.
Comment From: fhanik
For feature parity it would be reasonable to expect a ReactiveUserDetailsManager interface similar to its servlet counterpart
I agree that keeping a reference to the user map is not an ideal solution. One should not expect that the reference is the source of data inside the implementation, but rather the seed for the initial user set.
Would you be interested in contributing a PR?
Comment From: PyvesB
Would you be interested in contributing a PR?
Yes, I can give it a go!
Comment From: PyvesB
For feature parity it would be reasonable to expect a
ReactiveUserDetailsManagerinterface similar to its servlet counterpart
Just to clarify, are you suggesting to create a new ReactiveUserDetailsManager interface and make MapReactiveUserDetailsService implement it? If we closely follow the servlet equivalents, the hierarchy could look like the following:
ReactiveUserDetailsService
\ ReactiveUserDetailsPasswordService
ReactiveUserDetailsManager /
\ /
MapReactiveUserDetailsService
The issue with this approach is that MapReactiveUserDetailsService would be somewhat misnamed, it should ideally be called MapReactiveUserDetailsManager to be consistent with servlet implementations of UserDetailsManager (e.g. InMemoryUserDetailsManager, JdbcUserDetailsManager, LdapUserDetailsManager). It may need to change packages as well to keep all managers together (org.springframework.security.core.userdetails -> org.springframework.security.provisioning?). Renaming and/or moving would be a breaking change for users. Are such breaking changes acceptable or are we comfortable with the slight naming inconsistency introduced by the above graph?
Alternatively, we could keep the simpler and flatter structure we have today for reactive user detail classes:
ReactiveUserDetailsService ReactiveUserDetailsPasswordService
\ /
MapReactiveUserDetailsService
The new methods to add and remove users could simply be added to the existing ReactiveUserDetailsService interface. I'm leaning towards this approach as it doesn't directly impact users and keeps Spring's internal code simpler.
Comment From: marcusdacoregio
Closed since there is no need yet for this feature. See https://github.com/spring-projects/spring-security/pull/7762#issuecomment-981591388