Skip to content

Laravel Echo Plugin ​

File Information ​

  • Path: app/plugins/laravel-echo.client.ts
  • Purpose: Configure Laravel Echo for WebSocket communication with Pusher
  • Type: Client-only (runs only in browser)
  • Load Order: 5

Overview ​

The Laravel Echo plugin initializes Laravel Echo with Pusher for real-time WebSocket communication. It uses a secure server-side proxy for Pusher authentication, preventing XSS attacks by keeping the auth token in HTTP-only cookies.

Key Features ​

  1. Pusher Integration

    • Initializes Pusher.js library
    • Configures Pusher with key and cluster
    • Forces TLS for secure connections
  2. Secure Authentication

    • Uses server-side proxy for Pusher auth
    • Auth token stored in HTTP-only cookie
    • Prevents XSS attacks
    • Server API route handles authentication
  3. Laravel Echo Setup

    • Configures Echo broadcaster
    • Sets up secure authorizer
    • Makes Echo available globally
  4. WebSocket Communication

    • Real-time channel subscriptions
    • Private channel support
    • Presence channel support

Code Structure ​

typescript
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'

export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()

  // Initialize Pusher
  window.Pusher = Pusher

  // Initialize Laravel Echo
  window.Echo = new Echo({
    broadcaster: 'pusher',
    key: config.public.pusherKey || 'your-pusher-key',
    cluster: config.public.pusherCluster || 'mt1',
    forceTLS: true,
    authorizer: (channel, options) => {
      return {
        authorize: (socketId, callback) => {
          // Use secure server-side proxy
          $fetch('/api/pusher/auth', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
            },
            body: {
              socket_id: socketId,
              channel_name: channel.name,
            },
          })
            .then((data) => callback(false, data))
            .catch((error) => {
              console.error('[Laravel Echo] Pusher auth failed:', error)
              callback(true, error)
            })
        },
      }
    },
  })

  return {
    provide: {
      echo: window.Echo,
    },
  }
})

Configuration ​

Pusher Key ​

  • Config Path: config.public.pusherKey
  • Default: 'your-pusher-key'
  • Purpose: Pusher application key

Pusher Cluster ​

  • Config Path: config.public.pusherCluster
  • Default: 'mt1'
  • Purpose: Pusher cluster region
  • Note: Pusher automatically determines WebSocket endpoint from cluster

Force TLS ​

  • Value: true
  • Purpose: Ensures secure WebSocket connections

Secure Authentication ​

Server-Side Proxy ​

Instead of reading the auth token from cookies in JavaScript (which would expose it to XSS), the plugin uses a server-side proxy:

  1. Client Request: Echo requests authorization with socketId and channel_name
  2. Server Proxy: /api/pusher/auth endpoint reads HTTP-only auth_token cookie
  3. Pusher Auth: Server calls Pusher API to get authorization signature
  4. Response: Server returns authorization data to client
  5. Connection: Client uses authorization to connect to Pusher

Security Benefits ​

  • Auth token never exposed to JavaScript
  • HTTP-only cookie prevents XSS attacks
  • Server-side validation of channel access
  • Secure WebSocket connections (TLS)

Usage Examples ​

Listen to Public Channel ​

typescript
const { $echo } = useNuxtApp()

$echo.channel('public-channel')
  .listen('EventName', (data) => {
    console.log(data)
  })

Listen to Private Channel ​

typescript
const { $echo } = useNuxtApp()

$echo.private('private-channel')
  .listen('EventName', (data) => {
    console.log(data)
  })

Listen to Presence Channel ​

typescript
const { $echo } = useNuxtApp()

$echo.join('presence-channel')
  .here((users) => {
    console.log('Users here:', users)
  })
  .joining((user) => {
    console.log('User joining:', user)
  })
  .leaving((user) => {
    console.log('User leaving:', user)
  })

Stop Listening ​

typescript
const { $echo } = useNuxtApp()

$echo.leave('channel-name')

Server API Route ​

The plugin requires a server-side API route at /api/pusher/auth:

typescript
// server/api/pusher/auth.post.ts
export default defineEventHandler(async (event) => {
  // Read auth_token from HTTP-only cookie
  // Validate channel access
  // Call Pusher API for authorization
  // Return authorization data
})

Global Availability ​

Echo is available globally as:

  • window.Echo - Direct access
  • $echo - Via Nuxt app instance

Dependencies ​

  • Pusher.js - WebSocket library
  • Laravel Echo - Real-time event broadcasting
  • Server API Route - /api/pusher/auth for secure authentication

Security Considerations ​

  • Auth token stored in HTTP-only cookie
  • Server-side proxy prevents XSS attacks
  • TLS enforced for all connections
  • Channel authorization validated server-side

Notes for Development ​

  • Client-only plugin (.client.ts suffix)
  • Pusher cluster automatically determines endpoint
  • Secure authorizer prevents token exposure
  • Error handling for auth failures
  • Echo available globally via window and $echo