Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

bhosted's avatar

Laravel broadcasting / Echo / Websockets not authenticating

I'm trying to get Laravel broadcasting to work for several days now, but I get stuck on the authentication: no authentication is necessary to subscribe to a private channel. The components are:

  • Laravel 10
  • Laravel Echo
  • Beyondcode/Websockets

Everything is working, except for private channels: there is no authentication necessary to subscribe to a private channel. Even when the user is not logged in, subscribing to a private channel works.

In the browser I can see the /laravel-websockets/auth call is being done, but it always returns code 200:

Payload: socket_id=30081883.917483602&channel_name=private-user.2 {"auth":"df56f97:be1a81405d3e684cc37eda6636c0f6cbba4b9d96e7fef35ca104d7e8b5df6450"}

Any help would be appreciated!

Relevant route listings:

 GET|POST|HEAD   broadcasting/auth ... generated::vsh21TNBk5t8gQgU › Illuminate\Broadcasting › BroadcastController@authenticate
GET|HEAD        laravel-websockets ... generated::KHYhZLz6UI8zHoOP › BeyondCode\LaravelWebSockets › ShowDashboard  
GET|HEAD        laravel-websockets/api/{appId}/statistics ... generated::RmsumG9eoJZg6ehK › BeyondCode\LaravelWebSockets › DashboardApiController@getStatistics  
POST            laravel-websockets/auth ... generated::lH0Iy5EgmO81bJ2q › BeyondCode\LaravelWebSockets › AuthenticateDashboard  
POST            laravel-websockets/event ... generated::cKHH7Zjwb106yLAh › BeyondCode\LaravelWebSockets › SendMessage  
POST            laravel-websockets/statistics ... generated::ImoAzt5S4d4IdHdA › BeyondCode\LaravelWebSockets › WebSocketStatisticsEntriesController@store

.env

...
BROADCAST_DRIVER=pusher

MIX_PUSHER_APP_ID="${PUSHER_APP_ID}"
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MIX_PUSHER_APP_AUTH_PATH="${PUSHER_APP_AUTH_PATH}"

PUSHER_APP_ID=1595941
PUSHER_APP_KEY=df56f97
PUSHER_APP_SECRET=e1c0845dd0a
PUSHER_APP_CLUSTER=eu
PUSHER_APP_PATH="laravel-websockets"
PUSHER_APP_AUTH_PATH="/laravel-websockets/auth"
...

Laravel Echo javascript code

...
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    wsHost: window.location.hostname,
    wsPort: 6001,
    forceTLS: false,
    disableStats: true,
    enabledTransports: ['ws'],
    authEndpoint: process.env.MIX_PUSHER_APP_AUTH_PATH,
    auth: {
        headers: {
            'x-app-id': process.env.MIX_PUSHER_APP_ID
        },
    },
});

window.Echo.private('user.2')
    .listen('SendNotificationEvent', (e) => {
        console.log('user.notification event received' + e);
    });
...

config\broadcasting.php

<?php

return [

    'default' => env('BROADCAST_DRIVER', 'null'),

    'connections' => [

        'pusher' => [
            'driver'    => 'pusher',
            'key'       => env('PUSHER_APP_KEY'),
            'secret'    => env('PUSHER_APP_SECRET'),
            'app_id'    => env('PUSHER_APP_ID'),
            'options'   => [
                'cluster'   => env('PUSHER_APP_CLUSTER'),
                'host'      => '127.0.0.1',
                'port'      => 6001,
                'scheme'    => 'http'
            ],
        ],

        'redis' => [
            'driver'        => 'redis',
            'connection'    => 'default',
        ],

        'log' => [
            'driver'    => 'log',
        ],

        'null' => [
            'driver'    => 'null',
        ],

    ],

];

config\websockets.php

<?php

use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize;

return [

    'dashboard' => [
        'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
    ],

    'apps' => [
        [
            'id' => env('PUSHER_APP_ID'),
            'name' => env('APP_NAME'),
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'path' => env('PUSHER_APP_PATH'),
            'capacity' => null,
            'enable_client_messages' => false,
            'enable_statistics' => false,
        ],
    ],

    'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,

    'allowed_origins' => [
        //
    ],

    'max_request_size_in_kb' => 250,

    'path' => 'laravel-websockets',

    'middleware' => [
        'web',
        Authorize::class,
    ],

    'statistics' => [
        'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,

        'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,

        'interval_in_seconds' => 60,

        'delete_statistics_older_than_days' => 60,

        'perform_dns_lookup' => false,
    ],

    'ssl' => [
        'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),

        'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),

        'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
    ],

    'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
];

0 likes
3 replies
LaryAI's avatar
Level 58

It seems that the authentication is not working properly for private channels. The issue could be related to the configuration of the broadcasting driver or the websockets package. Here are some steps to troubleshoot the issue:

  1. Check the configuration of the broadcasting driver in the .env file. Make sure that the BROADCAST_DRIVER is set to pusher and the PUSHER_APP_* variables are set correctly.

  2. Check the configuration of the websockets package in the config/websockets.php file. Make sure that the path variable is set to laravel-websockets and the middleware array includes the Authorize middleware.

  3. Check the Laravel Echo javascript code in the application. Make sure that the authEndpoint variable is set to the correct URL for the authentication endpoint (/laravel-websockets/auth).

  4. Check the Laravel controller that handles the authentication request (BroadcastController@authenticate). Make sure that it returns a valid response with the authentication token for the private channel.

Here is an example of the BroadcastController@authenticate method:

public function authenticate(Request $request)
{
    $socketId = $request->input('socket_id');
    $channelName = $request->input('channel_name');

    // Authenticate the user for the private channel
    $user = Auth::user();
    $auth = $user ? $user->createToken('authToken')->accessToken : null;

    // Return the authentication response
    return response()->json([
        'auth' => $auth,
    ]);
}

Make sure that the Auth::user() method returns the authenticated user for the private channel.

If the issue persists, try enabling debug mode for the websockets package by setting the APP_DEBUG variable to true in the .env file. This will log any errors or exceptions that occur during the authentication process.

I hope this helps!

bhosted's avatar

@LaryAI Checked all steps, but that didn't fix the problem. Setting a breakpoint at BroadcastController@authenticate doesn't help: it doesn't get there.

bhosted's avatar

Solved my problem: In the Echo calls I was using the auth path of the Websockets dashboard. Changed it to broadcast/auth path and the main problem was solved. Had to add a second middleware to check if the user was already authentication using MFA and not only by the user / password combination.

Please or to participate in this conversation.