How to make Presence channels public

2023-08-14

This post assumes you have the initial set up of pusher & echo in Laravel

I wanted a way to keep track of users in a chat room where two things were important

  1. Signed in user list
  2. User count (including non signed in users)

Public channels made it work but not very smoothly.
Here's how it was handled

1. Signed in viewers

I had

  • A DB table(chat_users) with user_id and chat_id to keep track of active users
  • An onMounted hook that updated DB when a user joined
  • An unMounted hook that updated DB when a user left
  • A Cronjob that queried chat_users and pushed a list to each channel on a websocket

This was suboptimal because

  • Hooks were unreliable
  • State management was complex
  • Viewer list was not always up to date

2. Viewer count

Use the subscription_count hook available on public channels

The move to Presence channels

Presence channels made handling active viewers very easy because of the websocket hooks it offered. Presence channels offer

  • joined hook -> triggers when user joins chat, returns joining user
  • left hook -> triggers when user leaves chat, returns leaving user
  • here hook -> triggers when connection is made, returns active users

Handling viewer count got more difficult because

  1. Presence channels are private
  2. Presence channels lack the subscription_count hook

To fix this, I made a workaround to make presence channels allow guests.

Like with everything in laravel there's an easy work around.
Here's how auth in channels work & what i found.

Broadcast provider authentication

The authentication flow for channels goes

  1. Middlewares passed into Broadcast::routes() (or default if nothing is passed in) in app/Providers/BroadcastServiceProvider
  2. Broadcast channel route in channels.php

Guests fail the auth in step #1.
Here's how to get around that.

1. Generate a new middleware

We need to generate a middleware to pass in to Broadcast::routes()
This middleware is only for handling guests.
it should not affect auth users

  1. Run php artisan make:middleware AuthenticateGuest and add the code below

Middleware code

2. Register our middleware

  1. Add the middleware to app/Http/Kernel.php Kernel code
  2. Add it to BroadcastProvider.php Broadcast Provider code

The order matters, regular auth needs be first or every user would be a guest.

3. Confirm your channel authentication

This will make sure everyone has access to your channel Channel auth

and here is how it looks when guests join Here hook