How to use JWT with WebSocketChannel in Flutter

1,061

Solution 1

You are trying to send an object on the socket I think it is not happy with that. The server may not be able trop properly handle the error of receiving something other than a json string and closes the connection.

Try this to send a json string:

    var message = {
      "method": "auth",
      "accessToken": "${MY_TOKEN}"
    };

    _channel.sink.add(jsonEncode(message));

Solution 2

Give a try to this method. This is easy as mentioned in https://api.flutter.dev/flutter/dart-io/WebSocket/connect.html

  final WebSocketChannel channel =
  IOWebSocketChannel.connect("ws://<socketurl>/ws/",headers: {
    'Content-type': 'application/json',
   'Accept': 'application/json',
   'Authorization': 'Bearer $yourtoken'
  });

Solution 3

You may pass it in the URL:

WebSocketChannel.connect("ws://localhost:8080/api/foo/ws?authorization=eyJhbGciOiJIUzI1...")

Using IOWebSocketChannel as suggested throws a platform error if used with flutter web, whereas WebSocketChannel automatically determines the proper platform.

Traditionally it was considered poor practice to have credentials in query params because URLs can get stored in places such as logs for proxies, browser history, etc. However, neither of those concerns apply to websockets (a browser won't keep history of the connections made by a page), and proxies do not have access to the URL when there is a TLS tunnel. This concern arose when non-TLS interactions were the default.

source

Share:
1,061
francis_m
Author by

francis_m

Updated on December 13, 2022

Comments

  • francis_m
    francis_m over 1 year

    I have an existing Websocket Channel which needs authenticate user by his JWT in order to send/receive messages using this socket connection. The problem is - I don't know how to send my access token in message body when establishing connection. The official documentation says:

    "If the url contains user information this will be passed as basic authentication when setting up the connection."

    But in my case JWT is passed in a message like this:

    {"method":"auth","accessToken":"${MY_TOKEN}"}
    

    I tried to connect by passing JWT in headers or use sink after connection is established, but when I send a new message, it only calls onDone callback and closes connection.

      final _channel = IOWebSocketChannel.connect('${WEB_SOCKET_URL}');
    
    ...
    
      void initState() {
        _channel.stream.listen((message) {
          print('message');
        }, onError: (error, StackTrace stackTrace) {
          print('error');
        }, onDone: () {
          print('done');
        });
    
        _channel.sink.add({
          "method": "auth",
          "accessToken": "${MY_TOKEN}"
        });
    }
    

    I expect connection to be established and then I can use it to send/received messages but it's only closes when I try to use "sink.add()" method.

  • francis_m
    francis_m over 4 years
    Thanks for the response, but nope, still the same error.
  • Muldec
    Muldec over 4 years
    Do you enter onError or onDone?
  • francis_m
    francis_m over 4 years
    It enters onDone again
  • Ado Ren
    Ado Ren over 2 years
    This throws a platform error with flutter web.
  • Oliver Dixon
    Oliver Dixon about 2 years
    The headers don't work here. {"type":"connection_error","payload":{"message":"Cannot read properties of undefined (reading 'Authorization')"}}