jamiewest / signalr_core

ASP.NET Core SignalR Dart Client
https://pub.dev/packages/signalr_core
MIT License
90 stars 58 forks source link

Access token in the query string working fine in the connection establishing but not being sent in the next requests #78

Open motasemloubani91 opened 2 years ago

motasemloubani91 commented 2 years ago

The first request in the connection is authorized using the access token in the query string, but the next requests are not authorized and keep giving me 401, any help please, we are stuck

We are stuck now from days ago, we need asap support if possible, please?

mohachouch commented 2 years ago

Hi @motasemloubani91,

Can you share the source code.

Thanks

rho-cassiopeiae commented 2 years ago

@motasemloubani91 This is how it's supposed to work. The very first request after establishing a connection sends an initial http-request asking to upgrade the connection to websockets. Since it's an http-request, the middleware pipeline on the server runs and authenticates the request. Later messages on the same connection are part of the very same http-request, so no token is sent and no middleware runs, the messages go straight to the hub dispatcher on the server.

dromerolovo commented 9 months ago

@rho-cassiopeiae @mohachouch In my case. the client implementation is sending two request. The first one with the token (a regular http-request) and the second one a http request with the mentioned Upgrade header (to websockets), but this request doesn't have the Authorization header. So it can't go through the auth / authorization pipeline.

This is the first request headers read by the server: {"Host":["localhost:7180"],"User-Agent":["Dart/3.1 (dart:io)"],"Accept-Encoding":["gzip"],"Authorization":["<The token>"],"Content-Type":["text/plain;charset=UTF-8"],"Content-Length":["0"],"X-Requested-With":["FlutterHttpClient"]}

The second request: {"Connection":["Upgrade"],"Host":["localhost:7180"],"User-Agent":["Dart/3.1 (dart:io)"],"Accept-Encoding":["gzip"],"Cache-Control":["no-cache"],"Upgrade":["websocket"],"Sec-WebSocket-Version":["13"],"Sec-WebSocket-Extensions":["permessage-deflate; client_max_window_bits"],"Sec-WebSocket-Key":["hpOTyivyudEzVXj7ZTCVGw=="]}

This is the relevant part of the code:


start() async {
    var token = await firebaseAuth.currentUser!.getIdToken();
    var httpConnectionOptions = HttpConnectionOptions(
        accessTokenFactory: () => Future.delayed(Duration.zero, () => token!));
    try {
      _hubConnection = HubConnectionBuilder()
          .withUrl(
              "${await _settingsRepository.baseApiUrl(FlavorSingleton.flavor)}/hub/position-hub",
              httpConnectionOptions)
          .build();

      if (_hubConnection.state != HubConnectionState.connected) {
        await _hubConnection.start();
        print(_hubConnection.connectionId);
        _hubConnection.on("updatePositionToClient", (arguments) {});
      }
dromerolovo commented 9 months ago

As a hacky workaround I've added an Authorization header to the ws request in web_socket_channel_io.dart


var request = Request('GET', wsUri)
    ..headers.addAll({
      'Connection': 'Upgrade',
      'Authorization': 'Bearer $token',
      'Upgrade': 'websocket',
      'Sec-WebSocket-Key': nonce,
      'Cache-Control': 'no-cache',
      'Sec-WebSocket-Version': '13',
    });