pusher-channels-flutter icon indicating copy to clipboard operation
pusher-channels-flutter copied to clipboard

Can't Subscribe to Private Channel

Open JordanDalton opened this issue 2 years ago • 18 comments

I am attempting to subscribe to a private channel. The following is the instantiation of Pusher:

PusherChannelsFlutter pusher = PusherChannelsFlutter.getInstance();
var myChannelName = 'private-MyChannel';

try {

      await pusher.init(
        apiKey: '85fa4e3311f746a5ce25',
        cluster: 'us2',
        //authEndpoint: "https://9d1afc49846e.ngrok.io/mapi/auth",
        onConnectionStateChange: onConnectionStateChange,
        onError: onError,
        onSubscriptionSucceeded: onSubscriptionSucceeded,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onDecryptionFailure: onDecryptionFailure,
        onMemberAdded: onMemberAdded,
        onMemberRemoved: onMemberRemoved,
        onAuthorizer: onAuthorizer
      );
      await pusher.subscribe(channelName: myChannelName);
      await pusher.connect();
    } catch (e) {
      print("ERROR: $e");
    }

Given it's a private channel onAuthorizer get's called:

dynamic onAuthorizer(String channelName, String socketId, dynamic options) {

    print('////onAuthorizer');

    var response = Api().post('auth', {
      "socket_id": socketId,
      "channel_name": channelName,
    });

    var data = null;

    response.then((response){
      data = response.data;
      
      return jsonDecode(data); // {"auth":"<redacted>:<redacted>"}
    });
  }

On Pusher's debug console the Subscribed event never gets triggered.

JordanDalton avatar Mar 28 '22 14:03 JordanDalton

Do you receive any error messages when the subscription is attempted? You should see these in the client, or alternatively some error messages will be present in the Pusher Dashboard under the Error Log section?

It looks like your onAuthorizer code is making a request to an endpoint, can you share the code that returns the auth token from that endpoint?

benw-pusher avatar Mar 28 '22 14:03 benw-pusher

I received no success nor error message on the subscription. These are the callbacks I have defined:

  void onSubscriptionSucceeded(String channelName, dynamic data) {
    print("onSubscriptionSucceeded: $channelName data: $data");
  }

   void onSubscriptionError(String message, dynamic e) {
    print("onSubscriptionError: $message Exception: $e");
  }

Here's my controller from my Laravel app:

<?php

namespace App\Http\Controllers\MobileApi;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pusher\Pusher;

class PusherAuthController extends Controller
{
    public function __invoke(Request $request)
    {
        \Log::info('PusherAuthController', $request->toArray());

        $pusher = new Pusher(
            env('PUSHER_MOBILE_APP_KEY'),
            env('PUSHER_MOBILE_APP_SECRET'),
            env('PUSHER_MOBILE_APP_ID')
        );

        $channel     = request('channel_name');
        $socket_id   = request('socket_id');

        return $pusher->socket_auth($channel, $socket_id);
    }
}

This produces a response in the following format:

{"auth":"<redacted>:<redacted>"}

JordanDalton avatar Mar 28 '22 15:03 JordanDalton

I would expect that, if this authController is returning the auth token in the correct format (which it appears to be) then there should be an error emitted at the client. This error would likely be to indicate that the token returned is incorrect in some way. Are you able to open a support ticket so we can look up your app details and you can share the generated token and investigate? You can do so at support.pusher.com.

benw-pusher avatar Mar 28 '22 15:03 benw-pusher

I'll put in a ticket. My theory is that with onAuthorizer there's an async request to call my endpoint. Technically that method would return null before the API request completed.

JordanDalton avatar Mar 28 '22 16:03 JordanDalton

If authParams can offer support for Android and iOS this would resolve my issue.

JordanDalton avatar Mar 28 '22 17:03 JordanDalton

Can you try something like:

dynamic onAuthorizer(String channelName, String socketId, dynamic options) async {
    print('////onAuthorizer');
    var response = await Api().post('auth', {
      "socket_id": socketId,
      "channel_name": channelName,
    });
    return jsonDecode(response.data);
}

proggen-com avatar Mar 30 '22 06:03 proggen-com

I tried that but found that it only worked with public channels.

JordanDalton avatar Mar 30 '22 08:03 JordanDalton

This worked for me.

When using the onAuthorizer method, don't set the authEndpoint option when initializing pusher.

Future<void> _initializePusher() async {
    
    //singleton pusher instance
    var pusher= PusherChannelsFlutter.getInstance();

    await pusher.init(
        apiKey: pusherData.apiKey,
        cluster: pusherData.cluster,
        onError: onError,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onAuthorizer: onAuthorizer);

    channel = (await pusher.subscribe(channelName: channelName));
    await pusher.connect();
  }
dynamic onAuthorizer(
      String channelName, String socketId, dynamic options) async {
    var authUrl = baseUrl + '/broadcasting/auth';
    var result = await post(
      Uri.parse(authUrl),
      headers: {
         'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ${token}',
      },
      body: 'socket_id=' + socketId + '&channel_name=' + channelName,
    );
    return jsonDecode(result.body);
  }

solpreneur avatar Mar 30 '22 08:03 solpreneur

This worked for me.

When using the onAuthorizer method, don't set the authEndpoint option when initializing pusher.

Future<void> _initializePusher() async {
    
    //singleton pusher instance
    var pusher= PusherChannelsFlutter.getInstance();

    await pusher.init(
        apiKey: pusherData.apiKey,
        cluster: pusherData.cluster,
        onError: onError,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onAuthorizer: onAuthorizer);

    channel = (await pusher.subscribe(channelName: channelName));
    await pusher.connect();
  }
dynamic onAuthorizer(
      String channelName, String socketId, dynamic options) async {
    var authUrl = baseUrl + '/broadcasting/auth';
    var result = await post(
      Uri.parse(authUrl),
      headers: {
         'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ${token}',
      },
      body: 'socket_id=' + socketId + '&channel_name=' + channelName,
    );
    return jsonDecode(result.body);
  }

Hi, do you use laravel websockets pusher replacement method, if so where i have to set the Host name/address when initiate Pusher?

yacinegithub avatar Apr 14 '22 07:04 yacinegithub

@yacinegithub this https://github.com/pusher/pusher-channels-flutter/issues/41#issuecomment-1101549333 could help you

gtu-myowin avatar Apr 18 '22 16:04 gtu-myowin

This worked for me. When using the onAuthorizer method, don't set the authEndpoint option when initializing pusher.

Future<void> _initializePusher() async {
    
    //singleton pusher instance
    var pusher= PusherChannelsFlutter.getInstance();

    await pusher.init(
        apiKey: pusherData.apiKey,
        cluster: pusherData.cluster,
        onError: onError,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onAuthorizer: onAuthorizer);

    channel = (await pusher.subscribe(channelName: channelName));
    await pusher.connect();
  }
dynamic onAuthorizer(
      String channelName, String socketId, dynamic options) async {
    var authUrl = baseUrl + '/broadcasting/auth';
    var result = await post(
      Uri.parse(authUrl),
      headers: {
         'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ${token}',
      },
      body: 'socket_id=' + socketId + '&channel_name=' + channelName,
    );
    return jsonDecode(result.body);
  }

Hi, do you use laravel websockets pusher replacement method, if so where i have to set the Host name/address when initiate Pusher?

Same issue here, how can I insert custom port and host?

lailai0715 avatar Apr 21 '22 07:04 lailai0715

@lailai0715 You don't need those information. See the initialization here or my comment https://github.com/pusher/pusher-channels-flutter/issues/41#issuecomment-1101549333

gtu-myowin avatar Apr 22 '22 15:04 gtu-myowin

how to get socketId()?

kwul0208 avatar Aug 14 '22 06:08 kwul0208

Dear @solpreneur I get null from broadcusting/auth this is init

try {
      await pusher.init(
        apiKey: _apiKey.text,
        cluster: _cluster.text,
        onConnectionStateChange: onConnectionStateChange,
        onError: onError,
        onSubscriptionSucceeded: onSubscriptionSucceeded,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onDecryptionFailure: onDecryptionFailure,
        onMemberAdded: onMemberAdded,
        onMemberRemoved: onMemberRemoved,
        //authEndpoint: "https://my-website.com/broadcasting/auth",
        onAuthorizer: onAuthorizer,
      );
      await pusher.subscribe(channelName: _channelName.text);
      await pusher.connect();
    } catch (e) {
      print("$e");
      log("ERROR: $e");
    }

and this is the onAuthorizer function

 dynamic onAuthorizer(
      String channelName, String socketId, dynamic options) async {
    var authUrl = "https://my-website.com/broadcasting/auth";
    var result = await http.post(
      Uri.parse(authUrl),
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ${token}',
      },
      body: 'socket_id=' + socketId + '&channel_name=' + channelName,
    );
    return jsonDecode(result.body);
  }

I tried content-type as json too but same result

      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ${token}',
      }

this is the error I get

[  +65 ms] I/PusherChannelsFlutter(20214): Start com.pusher.client.Pusher@4083fc0
[ +102 ms] I/flutter (20214): LOG: Connection: CONNECTING
[+1566 ms] I/flutter (20214): LOG: Connection: CONNECTED
[+1566 ms] I/flutter (20214): LOG: onSubscriptionError: Unable to parse response from Authorizer: null Exception: com.pusher.client.AuthorizationFailureException: Unable to parse
response from Authorizer: null

the backend is Laravel the route broadcasting/auth is bydefault created

ziagit avatar Oct 03 '22 14:10 ziagit

@ziagit An empty response from broadcast/auth could indicate an error when generating the necessary token - for example the broadcast driver not being set correctly to the app credentials in the .env file being missing/invalid.

benw-pusher avatar Oct 04 '22 14:10 benw-pusher

@kwul0208 you can get the socket ID using the method described at https://github.com/pusher/pusher-channels-flutter#socket-information

benw-pusher avatar Oct 04 '22 14:10 benw-pusher

@benw-pusher can you provide a method to send AuthOptions with pusher.init i think it will solve the problem

mahmoudmaray2000 avatar Feb 08 '23 15:02 mahmoudmaray2000

I solved this problem, if anyone else has such a problem look here

ziagit avatar Feb 09 '23 16:02 ziagit