FleetbaseFleetbase

Migrating to Authenticated Socket Channels

What changes for API customers when Fleetbase socket channels require authentication, and how to move an existing real-time integration to short-lived socket tokens.

Migrating to Authenticated Socket Channels

Fleetbase real-time channels are moving from open subscriptions to authenticated subscriptions. Until now, anyone who knew a channel name such as company.{company_id} could subscribe to it. With authentication, every connection presents a short-lived socket token, and the socket server only allows the channels that token is entitled to.

This guide is for teams with their own integration that subscribes to Fleetbase socket channels. The Fleetbase console, Navigator app and Storefront app handle this themselves once they are up to date.

What Changes

BeforeAfter
ConnectingAnonymous connectionConnection carries a socket token from POST /v1/socket/token
Who can subscribeAnyone who knows the channel nameOnly tokens entitled to the channel. API-key tokens: the key's own company, its own api.{key_id} channel, and records of the same company.
Credentials in the browserSome examples put an API key in browser codeOnly the short-lived token reaches the browser. The API key stays on your server.
Token lifetimen/aMinutes (expires_in, 900 seconds by default). Refresh about 60 seconds before expiry.
Client publishingPossibleRefused in enforce mode. Only the Fleetbase API publishes events.

Channel names and event payloads do not change. company.{company_id}, api.{key_id} and resource channels such as order.{id} carry the same events as before.

Timeline

The change takes effect for you when your instance or Fleetbase Cloud enables enforce mode. Before that, socket authentication is either switched off or running in off or log mode, and anonymous subscriptions keep working, so you can migrate at your own pace and verify the new flow against the same server.

  • Switched off (SOCKETCLUSTER_AUTH_ENABLED not true, the default) — POST /v1/socket/token answers 404 and everything is allowed, as before.
  • off — everything is allowed, as before.
  • log — everything is still allowed, but subscriptions that would be denied are recorded so operators can see who has not migrated yet.
  • enforce — anonymous subscriptions and subscriptions to other companies' channels are rejected.

Code that follows this guide works in all of these states, so you can ship it before enforce is switched on.

Self-hosted instances

If you self-host, you decide when to switch. Socket authentication is controlled by these variables, set in the project .env file (Docker Compose passes them to the application, queue, scheduler and socket services):

VariableSet onValue
SOCKETCLUSTER_AUTH_ENABLEDAPI containers and socket serverfalse by default. true turns on the token routes, the authorize endpoint and signed publishing.
SOCKETCLUSTER_AUTH_KEYAPI containers and socket serverShared secret of at least 32 characters, identical everywhere
SOCKETCLUSTER_AUTH_MODEsocket serverlog, then enforce

Roll out in this order:

  1. Ship clients that request a token and connect without one when the token route answers 404 (current console, Navigator and Storefront apps, and integrations that follow this guide). Provision the key, keeping the switch off.
  2. Set SOCKETCLUSTER_AUTH_ENABLED=true on the API containers and the socket server, with the socket server in SOCKETCLUSTER_AUTH_MODE=log.
  3. Switch to enforce once the deny log only shows traffic you expect to lose.

enforce requires SOCKETCLUSTER_AUTH_ENABLED=true on the API: with the switch off, the API publishes over the legacy websocket path, which an enforcing socket server refuses. Details are in System Setup → Socket.

How to Migrate

Add a token endpoint to your server

Create an endpoint in your own backend that calls POST /v1/socket/token with your secret API key and returns the result to your signed-in users:

app.post('/realtime-token', requireSignedInUser, async (req, res) => {
    const response = await fetch('https://api.your-instance.com/v1/socket/token', {
        method: 'POST',
        headers: { Authorization: `Bearer ${process.env.FLEETBASE_SECRET_KEY}` },
    });
    res.status(response.status).json(await response.json()); // { token, expires_in, expires_at }
});

The official SDKs wrap this call: fleetbase.socket.token() in @fleetbase/sdk, and $fleetbase->socket->token() in fleetbase/fleetbase-php.

Remove API keys from client code

Search your front end and mobile apps for Fleetbase API keys. Anything that called the Fleetbase API directly from the browser — such as loading drivers or orders — should go through your server instead. If a key has been shipped in client code, rotate it in Developers → API Keys.

Connect with the token

Give socketcluster-client an in-memory authEngine whose loadToken() fetches a token from your endpoint, so the token is part of every connect and reconnect handshake. Refresh it with socket.authenticate(newToken) about 60 seconds before it expires, and re-authenticate on deauthenticate. The complete snippet is in Socket Events → Connect from the browser.

If you call socket.authenticate(token) yourself instead, do it before subscribing and after every reconnect.

Check your channels

Make sure every channel you subscribe to belongs to the company that owns the key:

  • company.{company_id} — your organization's UUID or public id
  • api.{key_id} — the UUID of the key that minted the token
  • order.{id}, driver.{id}, vehicle.{id}, … — records of the same company. A test-mode key resolves records in the sandbox.

Listen for subscribeFail on each channel during testing to catch names that will be rejected.

Stop publishing from clients

If your client code calls socket.transmitPublish(), transmit() or invoke(), move that logic to your server and use the Fleetbase API or webhooks instead. Client publishing is refused in enforce mode.

Handle servers without socket authentication

An instance that has not switched socket authentication on (SOCKETCLUSTER_AUTH_ENABLED off, or no key) answers POST /v1/socket/token with 404. Treat that as "connect without a token" so the same code runs against older self-hosted instances and instances that have not turned it on yet.

Checklist

  • No Fleetbase API key in browser, mobile or other client code
  • Server endpoint that mints socket tokens for signed-in users only
  • Token kept in memory (not localStorage, not in the WebSocket URL)
  • Token presented in the handshake (authEngine) or via socket.authenticate(token) before subscribing
  • Refresh about 60 seconds before expires_in elapses, and on deauthenticate
  • Only channels of your own company
  • No client-side publishing

FAQ

Migrating to Authenticated Socket Channels | Fleetbase