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 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:
My attempts to fix the error
- I tried to test the back-end with the postman, and the pusher debug console works fine:
- 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