Unable to connect using JWT
asafgo opened this issue · 9 comments
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}');
}
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
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,
);
I tired to following but still not working
final headers = {
HttpHeaders.authorizationHeader: 'Bearer $token',
};
final channel = IOWebSocketChannel.connect(
'wss://<my url>/progresshub',
headers: headers);
我尝试遵循但仍然无效
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
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.
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.
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();
- Why
await channel.sink.close(status.goingAway);
cause error? - What try..catch block does not capture any error?
try {
await channel.sink.close(status.goingAway);
} catch (e) {
print('Error: $e');
}
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 usingawait channel.sink.close();
- Why
await channel.sink.close(status.goingAway);
cause error?- 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');
}
}
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?
Use this:
import 'package:web_socket_channel/io.dart';
_channel = IOWebSocketChannel.connect(
url,
headers: {
'Authorization': 'Bearer $apiKey',
},
);