onveyor
Site menu
GitHub
Native Conveyor / Authorization Both modes

Authorization

Authorization depends on the protocol mode.

NativeUses Conveyor tokens.
Pusher/ReverbUses Laravel's normal broadcasting authorization.

Native server token Native

For trusted services only. The server token is a privileged credential used for WebSocket connections, fanout, HTTP publishing, and issuing temporary channel tokens. Keep it on infrastructure you control. Do not embed it in browser, mobile, or desktop applications distributed to users.

Set Constants::WEBSOCKET_SERVER_TOKEN when starting the server:

server.phpnative
<?php

use Conveyor\Constants;
use Conveyor\ConveyorServer;

require __DIR__ . '/vendor/autoload.php';

(new ConveyorServer())
    ->port(8989)
    ->conveyorOptions([
        Constants::WEBSOCKET_SERVER_TOKEN => 'local-server-token',
    ])
    ->start();

Trusted services using the native protocol pass the server token in the WebSocket handshake as a token query parameter. This localhost example is for development:

text
ws://127.0.0.1:8989?token=local-server-token

fanout-action also requires auth set to the server token.

Redact server credentials from logs. The reusable server token travels between trusted services, such as Laravel and Conveyor. Server-to-server URLs can still appear in proxy and access logs or monitoring traces. Omit or redact the token query parameter wherever these requests are recorded, for example /conveyor/auth?token=[REDACTED]. Replace the server token if it is exposed. The single-use temporary channel tokens described below are separate credentials; consuming one does not invalidate the server token.

Native temporary channel tokens Native

From your trusted application backend, create a token for one channel by posting to /conveyor/auth with the server token:

shell
curl -X POST "http://127.0.0.1:8989/conveyor/auth?token=local-server-token" \
  -H "Content-Type: application/json" \
  -d '{"channel":"orders.1"}'
jsonresponse
{
  "auth": "temporary-token"
}

Pass that value as auth in channel-connect:

json
{
  "action": "channel-connect",
  "channel": "orders.1",
  "auth": "temporary-token"
}

Temporary channel tokens are consumed after use, so each connection needs a new one.

Authorizing end-user applications

Your application backend should authenticate the user and check their access to the requested channel before calling /conveyor/auth. Return only the temporary channel token to an authorized app; keep the server token on the backend. Repeat the access check when issuing a replacement token.

Connection authorization must also be addressed. The native WebSocket handshake documented above uses the server token. A temporary channel token authorizes channel-connect; this example does not establish that it can replace the handshake credential. Before allowing direct connections from distributed apps, verify that your server supports a limited connection credential. If it requires the server token, use a backend proxy that enforces user and channel permissions, or implement limited connection authorization on the server. Do not give the app the server token to complete this flow.

Laravel Echo authorization Pusher/Reverb

In Pusher protocol mode, Conveyor validates Pusher channel signatures, but Laravel still handles user authorization.

Public channels

Public channels need no auth.

javascriptpusher/reverb
window.Echo.channel('orders')

Private channels

Private channels call Laravel's /broadcasting/auth.

javascriptpusher/reverb
window.Echo.private('orders.1')

Presence channels

Presence channels also call /broadcasting/auth, and the callback must return identifying user data, not just a boolean.

Point the WebSocket at Conveyor and auth at Laravel

javascriptpusher/reverb
window.Echo = new Echo({
  broadcaster: 'reverb',
  key: import.meta.env.VITE_REVERB_APP_KEY,
  wsHost: import.meta.env.VITE_REVERB_HOST,
  wsPort: import.meta.env.VITE_REVERB_PORT,
  wssPort: import.meta.env.VITE_REVERB_PORT,
  forceTLS: import.meta.env.VITE_REVERB_SCHEME === 'https',
  enabledTransports: ['ws', 'wss'],
  authEndpoint: `${import.meta.env.VITE_LARAVEL_URL}/broadcasting/auth`,
  auth: {
    withCredentials: true,
  },
})

Channel authorization callbacks stay in Laravel:

routes/channels.phppusher/reverb
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('orders.{orderId}', function ($user, int $orderId) {
    return $user->orders()->whereKey($orderId)->exists();
});

Broadcast::channel('room.{roomId}', function ($user, int $roomId) {
    if (! $user->rooms()->whereKey($roomId)->exists()) {
        return false;
    }

    return [
        'id' => $user->id,
        'name' => $user->name,
    ];
});

Signing in alone does not grant channel access. This example assumes orders() contains orders owned by the user and rooms() contains rooms they belong to. Adapt these relationships or use your application’s authorization policies. A user requesting another user’s order, or a room they have not joined, is denied access; presence user data is returned only after membership is confirmed.

If the auth request goes to a frontend dev server, the client is pointed at the wrong app. The request must reach Laravel.

Presence details — joining, leaving, and whispers — are on the Presence page.

Production security

The HTTP, WebSocket, and local-* credentials in these examples are for local development. Before exposing a deployment, apply the following controls in your application, reverse proxy, and network configuration. These are deployment requirements, not a claim that Conveyor provides configuration options for every control.

HTTPS and WSS

Serve public HTTP endpoints over HTTPS and browser WebSocket connections over WSS, using a valid certificate. A reverse proxy can terminate TLS and forward WebSocket upgrades to Conveyor on a private network. Configure production clients with the public hostname and HTTPS/WSS settings; use encrypted upstream transport too when traffic crosses an untrusted network.

Private internal ports and privileged endpoints

Bind Conveyor to loopback when the proxy runs on the same host, or to a private interface on a restricted container or service network. Keep internal listener ports such as 8989 and 8990 off the public network using firewall rules. Expose only the client routes required by your protocol through the proxy; restrict token issuance and privileged publishing routes to trusted application servers. Verify these restrictions from outside the private network.

Allowed origins and channel access

Allow only your intended browser origins, including their scheme, hostname, and port, at the WebSocket upgrade boundary. Enforce this in the proxy or application layer if your deployed server has no origin control. Reject unexpected origins and define an explicit policy for clients that send no Origin header. Origin checks do not authenticate non-browser clients; keep token checks and per-channel authorization in place. Configure HTTP CORS separately for browser authorization requests, with explicit origins when credentials are used.

Resource limits

Set and test connection caps, per-user or per-IP connection and request rates, message-size limits, idle timeouts, and backpressure or queue bounds in the layers that support them. Apply limits to WebSocket messages as well as HTTP requests; an HTTP request limiter alone does not limit messages after an upgrade. The documented Pusher REST limits of 10000 bytes for event data and 10 events per batch do not replace deployment-wide limits. Choose thresholds for your workload and verify oversized or excessive traffic is rejected.

Secrets and rotation

Replace all example tokens and secrets with strong, unique values stored in server-side environment configuration or a secret manager. Never put the native server token or app signing secret in browser bundles, public repositories, or VITE_* variables. The Pusher app key is a public client identifier; the app secret is not. A browser client that requires the shared native server token would expose that credential: choose an authorization design that keeps privileged credentials on trusted servers.

The native examples carry tokens in query strings. Redact those values from proxy, application, monitoring, and error logs; WSS protects transport but does not prevent logging at either endpoint. Rotate credentials periodically and after suspected exposure: update trusted issuers and consumers, reload or restart services as required, retire old values, and verify old credentials are rejected on new requests and handshakes. Test how existing connections and outstanding temporary tokens behave; disconnect or invalidate them explicitly where required rather than assuming rotation revokes them.