diff --git a/src/gateway/server.silent-scope-upgrade-reconnect.poc.test.ts b/src/gateway/server.silent-scope-upgrade-reconnect.poc.test.ts index 804bf02e32c..af503a615ae 100644 --- a/src/gateway/server.silent-scope-upgrade-reconnect.poc.test.ts +++ b/src/gateway/server.silent-scope-upgrade-reconnect.poc.test.ts @@ -18,6 +18,36 @@ import { installGatewayTestHooks({ scope: "suite" }); +async function expectRejectedScopeUpgradeAttempt({ + attempt, + requestedEvent, + deviceId, + token, +}: { + attempt: { error?: { details?: unknown } }; + requestedEvent: Promise; + deviceId: string; + token: string; +}) { + const pending = await devicePairingModule.listDevicePairing(); + expect(pending.pending).toHaveLength(1); + expect(((attempt.error?.details ?? {}) as { requestId?: unknown }).requestId).toBe( + pending.pending[0]?.requestId, + ); + + const requested = (await requestedEvent) as { + payload?: { requestId?: string; deviceId?: string; scopes?: string[] }; + }; + expect(requested.payload?.requestId).toBe(pending.pending[0]?.requestId); + expect(requested.payload?.deviceId).toBe(deviceId); + expect(requested.payload?.scopes).toEqual(["operator.admin"]); + + const paired = await getPairedDevice(deviceId); + expect(paired?.approvedScopes).toEqual(["operator.read"]); + expect(paired?.tokens?.operator?.scopes).toEqual(["operator.read"]); + expect(paired?.tokens?.operator?.token).toBe(token); +} + describe("gateway silent scope-upgrade reconnect", () => { test("does not silently widen a read-scoped paired device to admin on shared-auth reconnect", async () => { const started = await startServerWithClient("secret"); @@ -48,23 +78,12 @@ describe("gateway silent scope-upgrade reconnect", () => { expect(sharedAuthUpgradeAttempt.ok).toBe(false); expect(sharedAuthUpgradeAttempt.error?.message).toBe("pairing required"); - const pending = await devicePairingModule.listDevicePairing(); - expect(pending.pending).toHaveLength(1); - expect( - (sharedAuthUpgradeAttempt.error?.details as { requestId?: unknown; code?: string }) - ?.requestId, - ).toBe(pending.pending[0]?.requestId); - const requested = (await requestedEvent) as { - payload?: { requestId?: string; deviceId?: string; scopes?: string[] }; - }; - expect(requested.payload?.requestId).toBe(pending.pending[0]?.requestId); - expect(requested.payload?.deviceId).toBe(paired.deviceId); - expect(requested.payload?.scopes).toEqual(["operator.admin"]); - - const afterUpgradeAttempt = await getPairedDevice(paired.deviceId); - expect(afterUpgradeAttempt?.approvedScopes).toEqual(["operator.read"]); - expect(afterUpgradeAttempt?.tokens?.operator?.scopes).toEqual(["operator.read"]); - expect(afterUpgradeAttempt?.tokens?.operator?.token).toBe(paired.token); + await expectRejectedScopeUpgradeAttempt({ + attempt: sharedAuthUpgradeAttempt, + requestedEvent, + deviceId: paired.deviceId, + token: paired.token, + }); postAttemptDeviceTokenWs = await openTrackedWs(started.port); const afterUpgrade = await connectReq(postAttemptDeviceTokenWs, { @@ -120,23 +139,12 @@ describe("gateway silent scope-upgrade reconnect", () => { expect(reconnectAttempt.ok).toBe(false); expect(reconnectAttempt.error?.message).toBe("pairing required"); - const pending = await devicePairingModule.listDevicePairing(); - expect(pending.pending).toHaveLength(1); - expect( - (reconnectAttempt.error?.details as { requestId?: unknown; code?: string })?.requestId, - ).toBe(pending.pending[0]?.requestId); - - const requested = (await requestedEvent) as { - payload?: { requestId?: string; deviceId?: string; scopes?: string[] }; - }; - expect(requested.payload?.requestId).toBe(pending.pending[0]?.requestId); - expect(requested.payload?.deviceId).toBe(paired.deviceId); - expect(requested.payload?.scopes).toEqual(["operator.admin"]); - - const afterAttempt = await getPairedDevice(paired.deviceId); - expect(afterAttempt?.approvedScopes).toEqual(["operator.read"]); - expect(afterAttempt?.tokens?.operator?.scopes).toEqual(["operator.read"]); - expect(afterAttempt?.tokens?.operator?.token).toBe(paired.token); + await expectRejectedScopeUpgradeAttempt({ + attempt: reconnectAttempt, + requestedEvent, + deviceId: paired.deviceId, + token: paired.token, + }); } finally { watcherWs?.close(); backendReconnectWs?.close();