2

I've implemented a server using Spring Stomp and now I'm trying to connect to my server using stomp-js rx-stomp. What I find really awkward is that the JS implementation is not working, although I've managed to make it work using the Java stomp client.

Java client code(works):

WebSocketStompClient stompClient = new WebSocketStompClient(new SockJsClient(createTransportClient()));
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
final String URL = "http://localhost:" + port + "/ws";
// -< Headers used for authentication
WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
String user = "user1", pass = "abcd1234";
headers.add("Authorization", "Basic " + getBasicAuthToken(user, pass));
StompSession stompSession = stompClient.connect(URL, headers, new StompSessionHandlerAdapter() {
}).get(10, TimeUnit.SECONDS);

JS client code(doesn't work):

connect: function() {
    const stompConfig = {
        connectHeaders: {
            login: "user1",
            passcode: "abcd1234",
            Authorization: "Basic dXNlcjE6YWJjZDEyMzQ="
        },
        webSocketFactory: function() {
            return new SockJS("http://localhost:8080/ws");
        },
        reconnectDelay: 60000
    };
    rxStomp = new RxStomp.RxStomp();
    rxStomp.configure(stompConfig);
    rxStomp.activate();

    rxStomp.connected$.subscribe(res => {
        if (res === 1) console.log('connected');
        else console.log('not connected');
    });
}

First of all, I find really awkward that I see a prompt asking my to enter a username and a password. If I enter the credentials there then the client connects successfully. So, I thought that I must be doing something wrong regarding the connect headers. As you can see, I've tried to add the Basic Auth token there, hoping that it would solve something. It doesn't.

Cosmin Stoian
  • 757
  • 10
  • 15
  • Could it be that you need to set `access_token` instead of `Authorization` in connectHeaders? From stompjs docs : `Connection headers, important keys - login, passcode, host`. You seem to be missing `host`. If above doesn't work, it might be worth trying to set `access_token` in beforeConnect function? – Barzev Nov 27 '19 at 17:12
  • Just did that and it doesn't fix anything. What would this work though? Doesn't stomp-js send the headers as they are to the server? The Java client works by settings the header "Authorization". I thought it would be the same here. – Cosmin Stoian Nov 27 '19 at 17:16
  • It doesn't give me any errors about not specifying a host in the connectHeaders, so I don't think that I'm required to specify it. – Cosmin Stoian Nov 27 '19 at 17:19

1 Answers1

1

The Java and the Javascript versions of the code, even though similar, differ in an important way. The Java version sets the Authorization header in the underlying HTTP connection of the Websocket. However, in the Javascript version, the HTTP connection is made, and then the Authorization header is passed as the STOMP CONNECT frame.

The browser Websocket API or SockJS does not allow setting custom headers to the underlying HTTP connection, which is used by the Java version of the code in the question. To support authentication, the brokers need to support receiving authentication parameters as part of the CONNECT frame (exposed as connectHeaders in the JS Stomp clients).

Spring does not, by default, support authentication parameters as part of the CONNECT frame. Please see https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-stomp-authentication-token-based to support it.

Deepak Kumar
  • 944
  • 9
  • 12