Skip to content

Commit 82cba0c

Browse files
committed
test(gateway): verify device token is sent alongside shared credentials
Update connect-auth tests to assert that the stored device token is included in the auth payload even when an explicit shared token or password is provided. Previously the tests asserted deviceToken was undefined in these cases, matching the old suppression behavior. Add `deviceIdentity` to the Node.js client test fixtures so the stored-token lookup path is exercised (addresses the missing `deviceIdentity` config gap flagged during review of #39639).
1 parent 7252977 commit 82cba0c

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

src/gateway/client.test.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,17 @@ describe("GatewayClient connect auth payload", () => {
354354
);
355355
}
356356

357-
it("uses explicit shared token and does not inject stored device token", () => {
357+
it("sends stored device token alongside explicit shared token for fallback auth", () => {
358358
loadDeviceAuthTokenMock.mockReturnValue({ token: "stored-device-token" });
359+
const identity: DeviceIdentity = {
360+
deviceId: "dev-fallback-1",
361+
privateKeyPem: "private-key", // pragma: allowlist secret
362+
publicKeyPem: "public-key",
363+
};
359364
const client = new GatewayClient({
360365
url: "ws://127.0.0.1:18789",
361366
token: "shared-token",
367+
deviceIdentity: identity,
362368
});
363369

364370
client.start();
@@ -368,16 +374,22 @@ describe("GatewayClient connect auth payload", () => {
368374

369375
expect(connectFrameFrom(ws)).toMatchObject({
370376
token: "shared-token",
377+
deviceToken: "stored-device-token",
371378
});
372-
expect(connectFrameFrom(ws).deviceToken).toBeUndefined();
373379
client.stop();
374380
});
375381

376-
it("uses explicit shared password and does not inject stored device token", () => {
382+
it("sends stored device token alongside explicit shared password for fallback auth", () => {
377383
loadDeviceAuthTokenMock.mockReturnValue({ token: "stored-device-token" });
384+
const identity: DeviceIdentity = {
385+
deviceId: "dev-fallback-2",
386+
privateKeyPem: "private-key", // pragma: allowlist secret
387+
publicKeyPem: "public-key",
388+
};
378389
const client = new GatewayClient({
379390
url: "ws://127.0.0.1:18789",
380391
password: "shared-password", // pragma: allowlist secret
392+
deviceIdentity: identity,
381393
});
382394

383395
client.start();
@@ -387,9 +399,11 @@ describe("GatewayClient connect auth payload", () => {
387399

388400
expect(connectFrameFrom(ws)).toMatchObject({
389401
password: "shared-password", // pragma: allowlist secret
402+
deviceToken: "stored-device-token",
390403
});
391-
expect(connectFrameFrom(ws).token).toBeUndefined();
392-
expect(connectFrameFrom(ws).deviceToken).toBeUndefined();
404+
// When password is the primary credential, auth.token falls back to
405+
// the resolved device token for legacy compatibility.
406+
expect(connectFrameFrom(ws).token).toBe("stored-device-token");
393407
client.stop();
394408
});
395409

ui/src/ui/gateway.node.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ describe("GatewayBrowserClient", () => {
146146
vi.unstubAllGlobals();
147147
});
148148

149-
it("prefers explicit shared auth over cached device tokens", async () => {
149+
it("sends stored device token alongside explicit shared auth for fallback", async () => {
150150
const client = new GatewayBrowserClient({
151151
url: "ws://127.0.0.1:18789",
152152
token: "shared-auth-token",
@@ -165,13 +165,18 @@ describe("GatewayBrowserClient", () => {
165165
const connectFrame = JSON.parse(ws.sent.at(-1) ?? "{}") as {
166166
id?: string;
167167
method?: string;
168-
params?: { auth?: { token?: string } };
168+
params?: { auth?: { token?: string; deviceToken?: string } };
169169
};
170170
expect(typeof connectFrame.id).toBe("string");
171171
expect(connectFrame.method).toBe("connect");
172+
// Shared token takes priority for auth.token; device token is sent
173+
// alongside for gateway-side fallback (#39611, #39667, #44485).
172174
expect(connectFrame.params?.auth?.token).toBe("shared-auth-token");
175+
expect(connectFrame.params?.auth?.deviceToken).toBe("stored-device-token");
173176
expect(signDevicePayloadMock).toHaveBeenCalledWith("private-key", expect.any(String));
174177
const signedPayload = signDevicePayloadMock.mock.calls[0]?.[1];
178+
// The signed payload still uses the shared token (authToken), not the
179+
// stored device token, because explicitGatewayToken takes precedence.
175180
expect(signedPayload).toContain("|shared-auth-token|nonce-1");
176181
expect(signedPayload).not.toContain("stored-device-token");
177182
});

0 commit comments

Comments
 (0)