Comments (5)
I was finally able to reproduce the issue and solve it. It is important to call the callback on the custom authorizer:
function setupEcho() {
const token = useCookie('XSRF-TOKEN').value
const config = useRuntimeConfig()
channelName.value = 'room.' + roomsStore.currentRoom.roomUuid
console.log('Channel Name: ' + channelName)
if (!echo.value) {
echo.value = new Echo({
authorizer: (channel, options) => {
return {
authorize: (socketId, callback) => {
const request = $fetch(config.baseURL + '/broadcasting/auth', {
async onRequest({ request, options }) {
options.method = 'post'
options.body = {
socket_id: socketId,
channel_name: channel.name
}
options.headers = {'X-XSRF-TOKEN': token,
'Accept': 'application/json',
},
options.credentials = 'include'
},
})
request.then((response) => {
console.log(response)
callback(null, response)
})
}
};
},
broadcaster: 'pusher',
key: 'app-key',
cluster: 'mt1',
wsHost: 'localhost',
wsPort: 6001,
forceTLS: false,
disableStats: true,
encrypted: true,
auth: {
headers: {'X-XSRF-TOKEN': token,
'Accept': 'application/json',
},
},
enabledTransports: ['ws', 'wss'],
});
}
}
This part is the important one:
request.then((response) => {
console.log(response)
callback(null, response)
})
I am not sure what callback is used internally by Laravel Echo but it is obligatory for the subscription of private/presence channels to work. All examples in the docs use axios so I had to change some code to work with the fetch API (which is used by the ohmyfetch library). After calling the callback (with a null value as first parameter which seems a bit strange but is also mentioned in the Laravel Docs) the subscription works and I get the event data:
This issue was not easy to debug, because the same setup works perfectly fine with public channels (including the subscription!) and there are absolutely no errors in the console when trying the same with private channels.
The issue can be closed.
from echo.
Hi @NK0D1NG, I am unable to replicate this issue.
Your example code seemed quite complicated so I just set up a minimal example to confirm that I can subscribe to private channels.
I spun up a Soketi server with Docker, per their docs:
docker run -p 6001:6001 -p 9601:9601 quay.io/soketi/soketi:1.4-16-debian
I set up a fresh Laravel install with Laravel Breeze's Vue stack to scaffold out auth views.
I installed the Pusher and Echo packages:
composer require pusher/pusher-php-server
npm install --save-dev laravel-echo pusher-js
I configured my .env
as follows:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=app-id
PUSHER_APP_KEY=app-key
PUSHER_APP_SECRET=app-secret
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
I uncommented the default Echo configuration in resources/js/bootstrap.js
:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ? import.meta.env.VITE_PUSHER_HOST : `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
I then logged into the Laravel app and observed Echo connecting to Soketi:
I then uncommented App\Providers\BroadcastServiceProvider::class
in config.app
and set up a channel in routes/channels.php
:
Broadcast::channel('foo-channel', fn () => true);
I then created an event with artisan make:event FooEvent
and updated it to implement ShouldBroadcast
. I updated the constructor to accept a $message
and updated the broadcastOn
method to use the foo
channel:
class FooEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public string $message)
{
//
}
public function broadcastOn()
{
return new PrivateChannel('foo-channel');
}
}
In Dashboard.vue
I subscribed to the event on the private channel:
Echo.private('foo-channel')
.listen('FooEvent', (e) => {
console.log(e);
});
And observed that Echo made the auth request:
I then used Laravel Tinker to dispatch the event:
And saw it come through in the console:
Are you able to confirm whether the issue exists for you with a minimal setup like this? If not, is there something specific I should do to replicate the issue?
from echo.
Hey @jessarcher
thanks for investigating into this. The only difference to my setup could be the custom auth guard I am using:
from config/auth.php:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'vcs' => [
'driver' => 'session',
'provider' => 'clients',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'clients' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
],
from routes/channels.php:
Broadcast::channel('room.{ruuid}', function ($client, $ruuid) {
Log::info('Broadcasting.Channel: ' . $ruuid);
return $client->room_uuid == $ruuid;
}, ['guards' => ['vcs']]);
My
app/Providers/BroadcastServiceProvider.php:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes(['middleware' => 'web', 'guards' => 'vcs']);
require base_path('routes/channels.php');
}
}
This is also the reason why my Echo setup seems complicated. I am also using Laravel Sanctum with an external Vue SPA which authenticates using Laravel's default session driver as you can see. Everything is set up like described in the official docs and not the first time I am doing it like this. Because Laravel Sanctum requires the X-XSRF-TOKEN and the Session Cookie to be set and Laravel Echo does not send token/session cookie automatically I added it by myself using the custom authorizer. As well as the application/json header. The Vue SPA is a different repository/project. Authenticating using the custom guard works just fine (for normal API routes and for the channels as well as you can see in the images in my original post). Because I have no monorepo I wasn't able to setup a minimal example for this whole setup yet.
So maybe Echo has a problem with the custom guard?
Can you confirm a subscription message inside the websocket connection? What do your request/responses in the websocket connection look like? Is there a subscription/subscription succeeded message? Can you confirm it works in your minimal example using a custom guard and Laravel Sanctum? I am using just another Eloquent model like:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
use App\Traits\Uuids;
class Client extends Authenticatable
{
use HasFactory, HasApiTokens, HasRoles, Uuids;
protected $guard_name = "vcs";
public function room()
{
return $this->belongsTo(Room::class, 'room_uuid', 'uuid');
}
}
I also use Redis as my queue driver.
I can also confirm that the event is correctly fired (the Laravel Event Listener gets called and I can see the event payload in the Soketi Logs) - so the only thing missing is the subscription call for the private channel from Laravel Echo..
from echo.
By the way: I am not using axios - I am using the fetch API (The frontend is developed with NuxtJS which uses ohmyfetch as a fetch API dependency).
from echo.
@driesvints @jessarcher
I provided two demo repositories (links in the original post) which also demonstrate the issue. They should work out of the box after installing the dependencies. Please follow the README of the Laravel Backend Repo to do the setup and create a first user with a custom guard. Even with this simplified setup Laravel Echo does not subscribe to the private channel.
For the frontend just use the newly created user (model is called 'client') to login. Then click on the Join Room Chat button which calls the listen
-method - but the callback never gets executed and there is no subscription message in the websocket connection.
from echo.
Related Issues (20)
- #listenToAll for NullConnector HOT 1
- #encryptedPrivate does not work with NullConnector HOT 1
- PresenceChannel interface missing 'Whisper' method HOT 2
- Implement `.listenOnce` and `.isListening` HOT 1
- [Bug] PresenceChannel interface missing 'Whisper' method HOT 2
- Nuxtjs + VUE 2 to update vue 3 + vite not working echo HOT 2
- Always got pusher ouput while using socket.io HOT 1
- Not subscribing to Echo when you open SPA as PWA from Homescreen HOT 4
- All the names of the events must be prefixed with a dot HOT 1
- Uncaught TypeError: event is undefined HOT 2
- Connection fails in Chrome, works just fine in FF HOT 1
- Export connectors and channels alongside with Echo and abstract classes HOT 2
- Laravel Echo with Socket.io HOT 1
- Centrifugo Connector HOT 1
- Fatal error when using channel.listen HOT 3
- Leave channel and disconnect right after HOT 1
- listen method does not work HOT 1
- Dont can get the returns of websocket
- dont cant get returns in console.log of the websocket, HOT 2
- ReferenceError: Property 'Pusher' doesn't exist HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from echo.