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
| Before | After | |
|---|---|---|
| Connecting | Anonymous connection | Connection carries a socket token from POST /v1/socket/token |
| Who can subscribe | Anyone who knows the channel name | Only 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 browser | Some examples put an API key in browser code | Only the short-lived token reaches the browser. The API key stays on your server. |
| Token lifetime | n/a | Minutes (expires_in, 900 seconds by default). Refresh about 60 seconds before expiry. |
| Client publishing | Possible | Refused 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_ENABLEDnottrue, the default) —POST /v1/socket/tokenanswers404and 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):
| Variable | Set on | Value |
|---|---|---|
SOCKETCLUSTER_AUTH_ENABLED | API containers and socket server | false by default. true turns on the token routes, the authorize endpoint and signed publishing. |
SOCKETCLUSTER_AUTH_KEY | API containers and socket server | Shared secret of at least 32 characters, identical everywhere |
SOCKETCLUSTER_AUTH_MODE | socket server | log, then enforce |
Roll out in this order:
- 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. - Set
SOCKETCLUSTER_AUTH_ENABLED=trueon the API containers and the socket server, with the socket server inSOCKETCLUSTER_AUTH_MODE=log. - Switch to
enforceonce 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 idapi.{key_id}— the UUID of the key that minted the tokenorder.{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 viasocket.authenticate(token)before subscribing - Refresh about 60 seconds before
expires_inelapses, and ondeauthenticate - Only channels of your own company
- No client-side publishing
FAQ
Related
- Socket Events — channel reference and full connection example
- Set Up Real-Time Tracking — end-to-end recipe with a live map
- System Setup → Socket — self-hosting configuration and authentication modes