Home > other >  Cannot broadcast client event (connection not subscribed to channel private-chat)
Cannot broadcast client event (connection not subscribed to channel private-chat)

Time:11-15

I am building a real-time chat application with Laravel and Nuxt (Front-end and Back-end separated) using Pusher and Laravel-Echo, I have configured Laravel with pusher and it works fine and can see my requests in the Pusher debug console, I also want to mention two things first, I handle my authentication using Laravel-JWT and Nuxt-Auth and second, it works with public channels but since I converted it to private, Nuxt client can not subscribe anymore.

Here is error image: read connection but can not subscripe

Here is my Laravel config:

.env

BROADCAST_DRIVER=pusher
PUSHER_APP_ID=MY_APP_ID
PUSHER_APP_KEY=MY_APP_KEY
PUSHER_APP_SECRET=MY_APP_SECRET
PUSHER_APP_CLUSTER=eu

channels.php

Broadcast::channel('chat', function() {
    return true;
});

ChatController.php

public function sendMessage(Request $req) {
    $user = Auth::user();
        
    broadcast(new ChatEvent($user, $req->message))
        ->toOthers();
}

ChatEvent.php

public function __construct(User $user, $message)
    {
        $this->user = $user;
        $this->message = $message;
    }

public function broadcastAs()
    {
        return 'chat-event';
    }

public function broadcastOn()
    {
        return new PrivateChannel('chat');
    }

EventServiceProvider

use App\Events\ChatEvent;
use App\Listeners\SendMessageNotification;
...
protected $listen = [
        ChatEvent::class => [
            SendMessageNotification::class,
        ],
    ];

composer.json

"require": {
    ...
    "pusher/pusher-php-server": "^7.0",
    "tymon/jwt-auth": "^1.0"
}

Here is my Nuxt config:

package.json

"dependencies": {
    ...
    "@nuxtjs/auth-next": "5.0.0-1624817847.21691f1",
    "nuxt": "^2.14.6",
    "pusher-js": "^7.0.3",
  },
"devDependencies": {
    ...
    "@nuxtjs/laravel-echo": "^1.1.0",
  }

nuxt.config.js

buildModules: [
    ...
    '@nuxtjs/laravel-echo',
  ],
echo: {
    broadcaster: 'pusher',
    key: 'my-app-key',
    cluster: 'eu',
    forceTLS: true,
    plugins: ['~/plugins/echo.js']
  },

echo.js plugin

export default function ({ $echo }) {
    console.log($echo)
}

chat page index.vue

mounted() {
    this.$echo.private(`chat`)
      .listen(`chat-event`, (e) => {
        this.addNewMessage(e.user, e.message)
      })
      .listenForWhisper('typing', (e) => {
        console.log(e.name);
      })
  },
watch: {
    typeMessage() {
      this.$echo.private(`chat`)
        .whisper('typing', {
          name: this.typeMessage
        })
    }
  },

Here is my echo console log:

subscribed: false

My attempts to fix the error

  1. I tried to test the back-end with the postman, and the pusher debug console works fine: enter image description here
  2. I tried to change the channel to public, and it works fine.

Conclusion

I think the problem comes from the authentication part when trying to subscribe to a private channel, hope anyone can help!

CodePudding user response:

You are clearly facing a connection issue between your client and your API because of authentication.

Try with basic config without forceTLS (it must be also disabled in pusher website under App settings section).

In addition, be sure that your echo instance is hitting your auth endpoint with the required headers. It's needed for private/presence channels.

In my case I'm using passport so auth must be done with Bearer token attached in the header.

broadcaster: 'pusher',
key: process.env.VUE_APP_PUSHER_KEY,
cluster: process.env.VUE_APP_PUSHER_CLUSTER,
authEndpoint: process.env.VUE_APP_API_URL   '/broadcasting/auth',
auth: {
     headers: {
         Authorization: 'Bearer '   this.$auth.token()
     }
}

EDIT: sorry for not clarifying enough.

Presence/private channels are allowed only for authenticated users. Since you are using JWT you need to provide an Authorization header with the Bearer access token that you get when the user logs in.

I'm not sure how nuxt handles user tokens, but the this.$auth.token() is just a reference to how I retrieve a user's token by using websanova vue auth. But you may handle and store the token at the user's end in many ways

  • Related