Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to connect using JWT #378

Open
asafgo opened this issue Aug 4, 2024 · 9 comments
Open

Unable to connect using JWT #378

asafgo opened this issue Aug 4, 2024 · 9 comments

Comments

@asafgo
Copy link

asafgo commented Aug 4, 2024

Hi,

My Server side code is SignalR and I am unable to connect to it if I am using JWT. if I am not using JWT at server side, I am able to connect.

I am able to connect without any problem with same approach as my following Flutter code when using Postman and C# client code using web sockets.

My Flutter code:

final String token = '<The JWT Token>';
final String wsUrl ='wss://<Web Site URL>/progresshub?access_token==$token';
final wsURI = Uri.parse(wsUrl);
final channel = WebSocketChannel.connect(wsURI);

Also the following code does not return any error and channel object is empty:

try {
      await channel.ready;
    } on SocketException catch (e) {
      debugPrint('ERROR: - SocketException - ${e.message}');
      //print(e.message);
    } on WebSocketChannelException catch (e) {
      debugPrint('ERROR: - SocketException - ${e.message}');
    }

chanel empty

For some reason I am able to add sink's like so:

 channel.sink.add('{"protocol":"json","version":1}');

    channel.sink
        .add('{"type":1,"target":"AssociateJob","arguments":["$jobID"]}');

Error will raise without any location where it is when trying to listen:

channel.stream.listen(
      (message) {

But onError: (error) => debugPrint('Error: ' + error) is not triggered.

Thanks for any help,
AG

@leeyisoft
Copy link

leeyisoft commented Aug 4, 2024

It is normal for me to put the token in headers, you can refer to my code:
https://github.com/imboy-pub/imboy-flutter/blob/main/lib/service/websocket.dart

      _wsChannel = IOWebSocketChannel.connect(
        url!,
        headers: headers,
        pingInterval: Duration(milliseconds: _heartTimes),
        protocols: protocols,
      );

@asafgo
Copy link
Author

asafgo commented Aug 4, 2024

I tired to following but still not working

 final headers = {
      HttpHeaders.authorizationHeader: 'Bearer $token',
    };
    final channel = IOWebSocketChannel.connect(
        'wss://<my url>/progresshub',
        headers: headers);

@leeyisoft
Copy link

我尝试遵循但仍然无效

 final headers = {
      HttpHeaders.authorizationHeader: 'Bearer $token',
    };
    final channel = IOWebSocketChannel.connect(
        'wss://<my url>/progresshub',
        headers: headers);

Then the problem should be on the server side, please check the server side code

@asafgo
Copy link
Author

asafgo commented Aug 4, 2024

I don't think the problem is with server side as it work without any problem with Postman and C# client code using web sockets.

@leeyisoft
Copy link

leeyisoft commented Aug 5, 2024

It should be that your postman has some special configuration that your dart code doesn't have. Pay attention to the content-type setting
What I give below is erlang code, but the principle should be the same as C#, is dealing with http protocol, I guess your C# did not accept the parameters submitted by dart
Print some logs when you accept the parameters again to see if the parameters submitted by the dart code are the expected values

% -spec post_params(Req::cowboy_req:req()) -> proplists().
% imboy_req:post_params(Req0),
% PostVals = imboy_req:post_params(Req0),
post_params(Req) ->
    ContentType = cowboy_req:parse_header(<<"content-type">>, Req),
    % ?LOG([ContentType]),
    % imboy_log:info(io_lib:format("ContentType: ~p ContentType_End~n", [ContentType])),
    % ?LOG(Method = cowboy_req:method(Req)),
    case ContentType of
        % {<<"text">>,<<"plain">>, [{<<"charset">>,<<"utf-8">>}]} ->
        % {<<"text">>,<<"plain">>, _} ->
        %     [];
        {<<"application">>, <<"x-www-form-urlencoded">>, _} ->
            {ok, Params, _Req} = cowboy_req:read_urlencoded_body(Req, #{length => 640000000, period => 50000}),
            % imboy_log:info(io_lib:format("Params: ~p Params_End~n", [Params])),
            Params;
        {<<"application">>, <<"json">>, _} ->
            {ok, PostVals, _Req} = cowboy_req:read_body(Req),
            % ?LOG(PostVals),
            % Params = jsone:decode(PostVals, [{object_format, proplist}]),
            % ?LOG(Params),
            % Params
            jsone:decode(PostVals, [{object_format, proplist}]);
        _ ->
            imboy_log:error(io_lib:format("imboy_req:post_params error: ContentType ~p; ~p ~n", [ContentType, Req])),
            []
    end.

@asafgo
Copy link
Author

asafgo commented Aug 6, 2024

Using this code does work

final headers = {
      HttpHeaders.authorizationHeader: 'Bearer $token',
    };

final channel = IOWebSocketChannel.connect(wsUrl, headers: headers);

The code that cause the problem and confusion is the following that the Error is not capture in try..catch block for using await channel.sink.close(status.goingAway); but no error if using await channel.sink.close();

  1. Why await channel.sink.close(status.goingAway); cause error?
  2. What try..catch block does not capture any error?
try {
      await channel.sink.close(status.goingAway);
    } catch (e) {
      print('Error: $e');
    }

@leeyisoft
Copy link

Using this code does work

final headers = {
      HttpHeaders.authorizationHeader: 'Bearer $token',
    };

final channel = IOWebSocketChannel.connect(wsUrl, headers: headers);

The code that cause the problem and confusion is the following that the Error is not capture in try..catch block for using await channel.sink.close(status.goingAway); but no error if using await channel.sink.close();

  1. Why await channel.sink.close(status.goingAway); cause error?
  2. What try..catch block does not capture any error?
try {
      await channel.sink.close(status.goingAway);
    } catch (e) {
      print('Error: $e');
    }

I observe the following code, what is the value of your status.goingAway?
#0 checkCloseCode (package:web_socket/src/utils.dart:10:5)

/// Throw if the given close code is not valid.
void checkCloseCode(int? code) {
  if (code != null && code != 1000 && !(code >= 3000 && code <= 4999)) {
    throw ArgumentError('Invalid argument: $code, close code must be 1000 or '
        'in the range 3000-4999');
  }
}

@asafgo
Copy link
Author

asafgo commented Aug 7, 2024

status.dart from web_socket_channel give the option of 1001 that is const goingAway = 1001; so I don't understand if utils.dart allow only 1000 or range of 3000-4999 why status.dart give the option of status 1001 to status 1015?

@AndreyDAraya
Copy link

Use this:

 import 'package:web_socket_channel/io.dart';

      _channel = IOWebSocketChannel.connect(
        url,
        headers: {
          'Authorization': 'Bearer $apiKey',
        },
      );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants