Repository navigation
feat(socket-auth): authenticate realtime socket with driver socket tokens - #112
Merged
Merged
Conversation
resizePhoto measured Dimensions.get('window') — the device screen — rather
than the image at the given uri. Captured photos were scaled to the phone's
point size and into the screen's aspect ratio, so proof-of-delivery images
uploaded at a fraction of their real resolution.
Read the actual dimensions with Image.getSize, wrapped as a promise. On
failure it resolves null and resizePhoto returns the original uri, so an
unreadable image uploads full size rather than being lost.
Fixes #89
Fix POD photo resizing to use image dimensions instead of screen size
Release Navigator v2.0.11
Both prefixes are honoured so a release branch opened before the rename still releases. A merge that produces no tag and no publish looks exactly like a successful one, so the cutover is deliberately not a flag day.
ci(release): adopt the release/v* branch convention
…kens
Mint a short-lived socket token for the signed-in driver from
POST {host}/{namespace}/socket/token and deliver it in the SocketCluster
handshake through an in-memory auth engine. The token is refreshed a
minute before expiry, and re-fetched when the server deauthenticates the
socket, kicks it out of a channel or rejects a subscription; tracked
channels are then resubscribed. Servers without the route (404) and
signed-out sessions connect anonymously as before.
The socket is recreated on login, logout, organization switch and
instance-link changes, and identifies itself with a navigator/<version>
client tag in the handshake query.
This was referenced Oct 6, 2026
feat(socket-auth): show channel authorization failures in the sockets viewer
fleetbase/dev-engine#51
Merged
Merged
Merged
Conflicts came from the v2.0.11 release commits this branch carries: - src/utils/index.js: keep the image-dimension resize fix, in v3's JSDoc style - translations/en.json: keep v3's strings and main's location disclosure copy; drop the unused skipForNow - package.json: drop main's jest key, which collides with v3's jest.config.js; its modulePathIgnorePatterns move there
This was referenced Oct 14, 2026
Draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Authenticates the driver app's realtime (SocketCluster) connection with a short-lived socket token, as part of authenticated realtime channels.
src/services/socket-auth.ts):POST {host}/{namespace}/socket/tokenwith the driver's bearer token (same host/namespace the SDK adapter uses, defaultv1). Response{token, expires_in, expires_at}.socketClusterClient.create:loadTokenfetches a fresh token when there is none or it is within 60 s of expiry;saveToken/removeTokenkeep it in memory only. The token never touches MMKV/localStorage and never goes in the socket URL.expires_in - 60 sviasocket.authenticate(newToken)(expiry measured against the device clock fromexpires_in, so clock skew does not matter).deauthenticateor a channelkickOut, fetch a new token, re-authenticate and resubscribe every channel the app still listens to.subscribeFailon a tracked channel retries the same way with backoff (1 s, 2 s, 4 s), then gives up. Channels are tracked from the provider'ssubscribeChannel/closeChannel/killChannel.AuthContextexposes asessionEpochcounter so an org switch re-authenticates even if the bearer token string does not change.query: { client: 'navigator/<app version>' }(version fromDeviceInfoon native,package.jsonon web).Small fixes this needed:
subscribeChannelused to wait forever when a subscription was rejected. It now settles onsubscribeorsubscribeFail. On a rejection it still returns the channel, so the retry delivers data to the same listener.OrderScreennow clears its listener ref on cleanup so it re-subscribes when the socket is recreated.Why
Realtime channels are moving to authenticated subscriptions. With this change the driver app can only subscribe to channels the server authorizes for the signed-in driver.
Behaviour on older servers
The instance-link deep link can point this app at any self-hosted instance, including ones without socket auth. A
404from the mint route (or no signed-in driver) means the socket connects anonymously, as it does today. The 404 is remembered for that socket session, so the app does not retry on every reconnect. Other mint failures (network, 5xx) also fall back to anonymous, with a 30 s retry backoff.Test plan
__tests__/SocketAuth-test.jscover the token request, the 404 and no-driver anonymous fallback, the 60 s expiry window, the refresh timer, deauthenticate/kickOut recovery and resubscribe, subscribeFail backoff, and teardown.Related PRs
Part of the authenticated realtime channels rollout (socket auth), one PR per repo:
fleetbase/core-api ^1.6.69)fleetbase/fleetbase-socketserver, compose/helm/installer, console socket test page