diff --git a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java index dd307f655f0..4d09ad8c407 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java +++ b/config/src/main/java/org/springframework/security/config/annotation/rsocket/RSocketSecurity.java @@ -104,6 +104,7 @@ * } * * @author Rob Winch + * @author Ebert Toribio * @since 5.2 */ public class RSocketSecurity { @@ -320,6 +321,10 @@ public AuthorizePayloadsSpec permitAll() { .just(new AuthorizationDecision(true))); } + public AuthorizePayloadsSpec hasAnyAuthority(String... authorities) { + return access(AuthorityReactiveAuthorizationManager.hasAnyAuthority(authorities)); + } + public AuthorizePayloadsSpec access( ReactiveAuthorizationManager authorization) { AuthorizePayloadsSpec.this.authzBuilder.add(new PayloadExchangeMatcherEntry<>(this.matcher, authorization)); diff --git a/config/src/test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java b/config/src/test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java index 7641ce9a6ad..c5a8169c229 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/rsocket/RSocketMessageHandlerConnectionITests.java @@ -51,6 +51,7 @@ /** * @author Rob Winch + * @author Ebert Toribio */ @ContextConfiguration @RunWith(SpringRunner.class) @@ -167,6 +168,23 @@ public void connectWhenNotAuthorized() { // .isInstanceOf(RejectedSetupException.class); } + @Test + public void connectWithAnyAuthority() { + UsernamePasswordMetadata credentials = + new UsernamePasswordMetadata("ebert", "ebert"); + this.requester = requester() + .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE) + .connectTcp(this.server.address().getHostName(), this.server.address().getPort()) + .block(); + + String hiEbert = this.requester.route("management.users") + .data("ebert") + .retrieveMono(String.class) + .block(); + + assertThat(hiEbert).isEqualTo("Hi ebert"); + } + private RSocketRequester.Builder requester() { return RSocketRequester.builder() .rsocketStrategies(this.handler.getRSocketStrategies()); @@ -208,13 +226,18 @@ MapReactiveUserDetailsService uds() { .password("password") .roles("USER", "SETUP") .build(); + UserDetails manager = User.withDefaultPasswordEncoder() + .username("ebert") + .password("ebert") + .roles("SETUP", "MANAGER") + .build(); UserDetails evil = User.withDefaultPasswordEncoder() .username("evil") .password("password") .roles("EVIL") .build(); - return new MapReactiveUserDetailsService(admin, user, evil); + return new MapReactiveUserDetailsService(admin, user, manager, evil); } @Bean @@ -225,6 +248,7 @@ PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) { .setup().hasRole("SETUP") .route("secure.admin.*").hasRole("ADMIN") .route("secure.**").hasRole("USER") + .route("management.*").hasAnyAuthority("ROLE_MANAGER") .anyRequest().permitAll() ) .basicAuthentication(Customizer.withDefaults());