diff --git a/src/gateway/client.test.ts b/src/gateway/client.test.ts index 0d2346efb85..04ddc5027d4 100644 --- a/src/gateway/client.test.ts +++ b/src/gateway/client.test.ts @@ -402,6 +402,26 @@ describe("GatewayClient connect auth payload", () => { client.stop(); }); + it("uses explicit shared password and does not inject stored device token", () => { + loadDeviceAuthTokenMock.mockReturnValue({ token: "stored-device-token" }); + const client = new GatewayClient({ + url: "ws://127.0.0.1:18789", + password: "shared-password", // pragma: allowlist secret + }); + + client.start(); + const ws = getLatestWs(); + ws.emitOpen(); + emitConnectChallenge(ws); + + expect(connectFrameFrom(ws)).toMatchObject({ + password: "shared-password", // pragma: allowlist secret + }); + expect(connectFrameFrom(ws).token).toBeUndefined(); + expect(connectFrameFrom(ws).deviceToken).toBeUndefined(); + client.stop(); + }); + it("uses stored device token when shared token is not provided", () => { loadDeviceAuthTokenMock.mockReturnValue({ token: "stored-device-token" }); const client = new GatewayClient({ diff --git a/src/gateway/client.ts b/src/gateway/client.ts index a22d3471bb4..4641545ea8e 100644 --- a/src/gateway/client.ts +++ b/src/gateway/client.ts @@ -254,9 +254,12 @@ export class GatewayClient { ? loadDeviceAuthToken({ deviceId: this.opts.deviceIdentity.deviceId, role })?.token : null; // Keep shared gateway credentials explicit. Persisted per-device tokens only - // participate when no explicit shared token is provided. + // participate when no explicit shared token/password is provided. const resolvedDeviceToken = - explicitDeviceToken ?? (!explicitGatewayToken ? (storedToken ?? undefined) : undefined); + explicitDeviceToken ?? + (!(explicitGatewayToken || this.opts.password?.trim()) + ? (storedToken ?? undefined) + : undefined); // Legacy compatibility: keep `auth.token` populated for device-token auth when // no explicit shared token is present. const authToken = explicitGatewayToken ?? resolvedDeviceToken;