Search code examples
reactjsspring-bootspring-securityspring-websocket

Error connect to Spring-boot-Rsocket (Auth JWT) from web-client RSocketWebSocketClient


The connection to server with spring-boot client works good:

public RSocketAdapter() throws IOException {
    requester = createRSocketRequesterBuilder()
    .connectWebSocket(URI.create("ws://localhost:7878/"))
    .block();
}
private RSocketRequester.Builder createRSocketRequesterBuilder() {
    RSocketStrategies strategies = RSocketStrategies.builder()
    .encoders(encoders -> encoders.add(new Jackson2CborEncoder()))
    .decoders(decoders -> decoders.add(new Jackson2CborDecoder()))
    .dataBufferFactory(new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT))
    .build();
    return RSocketRequester.builder().rsocketStrategies(strategies);
}

public Mono<HelloToken> signIn(String principal, String credential) {
    return requester
            .route("signin.v1")
            .data(HelloUser.builder().userId(principal).password(credential).build())
            .retrieveMono(HelloToken.class)
            .doOnNext(token -> {
                accessToken = token.getAccessToken();
            })
            .onErrorStop();
}

And server receives such frame:

Correct byte frame

But the same request from web-client:

authSocketReactiv = () => {    
    const maxRSocketRequestN = 2147483647;    
    const keepAlive = 60000;
    const lifetime = 180000;
    const dataMimeType = 'application/json';
    const metadataMimeType = 'message/x.rsocket.authentication.bearer.v0';
    
    var client = new RSocketClient({
      serializers: {
        data: JsonSerializer,
        metadata: JsonSerializer,
      },
      setup: {
        dataMimeType,
        keepAlive,
        lifetime,
        metadataMimeType
      },
      transport: new RSocketWebSocketClient({
        url: 'ws://localhost:7878'                
      },Encoders)
    });

    // Open the connection
    client.connect().subscribe({
    onComplete: socket => {
      socket.requestStream({
        data:{
          'user_id': '0000',
          'password': 'Zero4'
        },
        metadata:'signin.v1'

      }).subscribe({
        onComplete: () => console.log('complete'),
        onError: error => {
          console.log(error);
        },
        onNext: payload => {
          console.log('Subscribe1');
        },
        onSubscribe: subscription => {
          console.log('Subscribe');
          subscription.request(2147483647);
        },
      });
    },
    onError: error => {
      console.log(error);
    },
    onSubscribe: cancel => {
     
    }
  });

Forms the incorrect frame and fall with “metadata is malformed ERROR” :

Error byte frame from web

What encoding or buffering options should be used here? Thanks for any tips and suggestions.


Solution

  • You are likely going to want to work with composite metadata and set your metadataMimeType to MESSAGE_RSOCKET_COMPOSITE_METADATA.string.

    The important bit is going to be the routing metadata, which is what tells the server how to route the incoming RSocket request.

    I haven't dug through the server example code you linked on StackOverflow, but just by looking at your example code, you would supply the routing metadata with your requestStream as so:

    Also, the example project you listed though references signin as a request/response so you actually don't want requestStream, but requestResponse.

    socket
      .requestResponse({
        data: Buffer.from(JSON.stringify({
          user_id: '0000',
          password: 'Zero4'
        })),
        metadata: encodeCompositeMetadata([
          [MESSAGE_RSOCKET_ROUTING, encodeRoute("signin.v1")],
        ]),
      })
    

    You will likely want to use BufferEncoders, as shown in this example. And additionally, I believe you should not use JsonSerializer for the metadata, but instead IdentitySerializer, which will pass the composite metadata buffer straight through, rather than trying to serialize to and from JSON.

    You may still run into some issues, but I suspect that this will get you past the metadata is malformed ERROR error.

    Hope that helps.