Search code examples
spring-bootspring-securityrsocket

How to configure RSocket security in a Spring Boot application with Spring Security


RSocket seems to be a nice alternative to HTTP/S for microservice to microservice communication. Fortunately Spring Boot already has a smooth integration that eases the configuration of it.

However I am missing information about everything related to RSocket security, both in RSocket and Spring (Boot, Security) documentation.

My questions are:

1) How can we configure RSocket to use TLS (in the context of a Spring Boot application)?

2) Does Spring Security add any additional features to RSocket security? Things that come to my head, imagine we want to propagate a JWT token from one application to another, how could it be passed and validated through an RSocket?


Solution

  • I recently wrote a post on how to use Spring Security Basic Authentication with RSocket. In for your first question, You can use TcpClientTransport.create(TcpClient.create().port(7000).secure()) when connecting to RSocketServer.

    RSocketRequester.builder()
                    .dataMimeType(MimeTypeUtils.APPLICATION_JSON)
                    .rsocketStrategies(rSocketStrategies)
                    .rsocketFactory(clientRSocketFactory -> {
                        clientRSocketFactory.frameDecoder(PayloadDecoder.ZERO_COPY);
                    })
                    .setupMetadata(credentials, UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE)
                    .connect(TcpClientTransport.create(TcpClient.create().port(7000).secure()))
                    .block();
    

    And for the second question, When accessing RSocket message endpoints you can use

            BearerTokenMetadata credentials = new BearerTokenMetadata("jwt-token");
            return rSocketRequester
                    .route("taxis")
                    .metadata(credentials, BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
                    .data(new TaxisRequest(type, from, to))
                    .retrieveMono(TaxisResponse.class);
    

    And during RSocketServer setup for the PayloadSocketAcceptorInterceptor you can use jwt as below.

        @Bean
        public PayloadSocketAcceptorInterceptor rsocketInterceptor(RSocketSecurity rsocket) {
            rsocket.authorizePayload(authorize -> {
                authorize
                        // must have ROLE_SETUP to make connection
                        .setup().hasRole("SETUP")
                        // must have ROLE_ADMIN for routes starting with "taxis."
                        .route("taxis*").hasRole("ADMIN")
                        // any other request must be authenticated for
                        .anyRequest().authenticated();
                })
                .jwt(Customizer.withDefaults());
    
                return rsocket.build();
            }