Overview
Secure WebSockets with Authentication in Laravel 11 (Reverb & Laravel Echo)
By default, Laravel Reverb allows public and private channels. To secure WebSockets, we need authenticated private channels.
Step 1: Enable Laravel Authentication Middleware
Ensure your Laravel app has authentication. If you haven’t set it up, run:
php artisan make:auth # For Laravel Breeze / Jetstream users
For API authentication, use Laravel Sanctum:
composer require laravel/sanctum php artisan sanctum:install
Then, add Sanctum’s middleware in app/Http/Kernel.php
:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
Step 2: Define Private Channel Authorization
Modify routes/channels.php to authorize users before they subscribe to WebSocket channels.
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('notifications', function ($user) {
return $user != null; // Only authenticated users can join
});
This ensures that only logged-in users can access the notifications
channel.
Step 3: Configure Laravel Echo with Authentication
Modify resources/js/bootstrap.js to include authentication:
import Echo from "laravel-echo"; import Pusher from "pusher-js";
window.Echo = new Echo({
broadcaster: "pusher",
key: "anykey", // Not required for Reverb
wsHost: window.location.hostname,
wsPort: 6001,
forceTLS: false,
disableStats: true,
authEndpoint: "/broadcasting/auth", // Laravel's default auth endpoint
auth: {
headers: {
Authorization: `Bearer ${localStorage.getItem("auth_token")}`, // Use stored token for API authentication
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
},
},
});
Step 4: Modify Event to Use Private Channels
Modify app/Events/NewNotification.php:
use Illuminate\Broadcasting\PrivateChannel;
public function broadcastOn() {
return new PrivateChannel('notifications'); // Private channel
}
Step 5: Send Notifications Only to Authenticated Users
Modify routes/web.php
to send notifications to logged-in users:
use App\Events\NewNotification; use Illuminate\Support\Facades\Route;
Route::middleware('auth:sanctum')->get('/send-notification', function () {
broadcast(new NewNotification("Hello, authenticated user!"));
return response()->json(['message' => 'Notification sent']);
});
Step 6: Listen for Authenticated Notifications in JavaScript
Modify your JS frontend:
window.Echo.private("notifications")
.listen(".new-notification", (e) => {
console.log("New Notification:", e.message);
});
Step 7: Restart Everything
Run these commands:
php artisan cache:clear
php artisan config:clear
php artisan reverb:start
npm run dev
php artisan serve
✅ Final Security Check
-
Login as an authenticated user
-
Visit:
http://127.0.0.1:8000/send-notification
-
Check browser console (F12 > Console) → Should see
"New Notification: Hello, authenticated user!"
-
If not logged in, WebSocket should NOT connect
🔥 Final Security Summary
✅ Only logged-in users can access WebSockets
✅ Laravel Echo now authenticates requests
✅ Private channels require authorization
✅ Sanctum protects API requests
This setup prevents unauthorized users from receiving notifications. 🎯