From 389de66b25fd59f2acef4779638109da90c7e9e5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 18:32:30 +0000 Subject: [PATCH] refactor: share browser auth test helpers --- .../server.auth.browser-hardening.test.ts | 156 +++++++----------- 1 file changed, 57 insertions(+), 99 deletions(-) diff --git a/src/gateway/server.auth.browser-hardening.test.ts b/src/gateway/server.auth.browser-hardening.test.ts index c31fb7c19b1..b28f60ad8c6 100644 --- a/src/gateway/server.auth.browser-hardening.test.ts +++ b/src/gateway/server.auth.browser-hardening.test.ts @@ -30,6 +30,11 @@ const TEST_OPERATOR_CLIENT = { mode: GATEWAY_CLIENT_MODES.TEST, }; const ALLOWED_BROWSER_ORIGIN = "https://control.example.com"; +const TRUSTED_PROXY_BROWSER_HEADERS = { + "x-forwarded-for": "203.0.113.50", + "x-forwarded-proto": "https", + "x-forwarded-user": "operator@example.com", +}; const originForPort = (port: number) => `http://127.0.0.1:${port}`; @@ -75,120 +80,73 @@ async function createSignedDevice(params: { }; } -describe("gateway auth browser hardening", () => { - test("rejects trusted-proxy browser connects from origins outside the allowlist", async () => { - const { writeConfigFile } = await import("../config/config.js"); - await writeConfigFile({ - gateway: { - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-forwarded-user", - requiredHeaders: ["x-forwarded-proto"], - }, - }, - trustedProxies: ["127.0.0.1"], - controlUi: { - allowedOrigins: [ALLOWED_BROWSER_ORIGIN], +async function writeTrustedProxyBrowserAuthConfig() { + const { writeConfigFile } = await import("../config/config.js"); + await writeConfigFile({ + gateway: { + auth: { + mode: "trusted-proxy", + trustedProxy: { + userHeader: "x-forwarded-user", + requiredHeaders: ["x-forwarded-proto"], }, }, - }); + trustedProxies: ["127.0.0.1"], + controlUi: { + allowedOrigins: [ALLOWED_BROWSER_ORIGIN], + }, + }, + }); +} - await withGatewayServer(async ({ port }) => { - const ws = await openWs(port, { - origin: "https://evil.example", - "x-forwarded-for": "203.0.113.50", - "x-forwarded-proto": "https", - "x-forwarded-user": "operator@example.com", +async function withTrustedProxyBrowserWs(origin: string, run: (ws: WebSocket) => Promise) { + await writeTrustedProxyBrowserAuthConfig(); + await withGatewayServer(async ({ port }) => { + const ws = await openWs(port, { + origin, + ...TRUSTED_PROXY_BROWSER_HEADERS, + }); + try { + await run(ws); + } finally { + ws.close(); + } + }); +} + +describe("gateway auth browser hardening", () => { + test("rejects trusted-proxy browser connects from origins outside the allowlist", async () => { + await withTrustedProxyBrowserWs("https://evil.example", async (ws) => { + const res = await connectReq(ws, { + client: TEST_OPERATOR_CLIENT, + device: null, }); - try { - const res = await connectReq(ws, { - client: TEST_OPERATOR_CLIENT, - device: null, - }); - expect(res.ok).toBe(false); - expect(res.error?.message ?? "").toContain("origin not allowed"); - } finally { - ws.close(); - } + expect(res.ok).toBe(false); + expect(res.error?.message ?? "").toContain("origin not allowed"); }); }); test("accepts trusted-proxy browser connects from allowed origins", async () => { - const { writeConfigFile } = await import("../config/config.js"); - await writeConfigFile({ - gateway: { - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-forwarded-user", - requiredHeaders: ["x-forwarded-proto"], - }, - }, - trustedProxies: ["127.0.0.1"], - controlUi: { - allowedOrigins: [ALLOWED_BROWSER_ORIGIN], - }, - }, - }); - - await withGatewayServer(async ({ port }) => { - const ws = await openWs(port, { - origin: ALLOWED_BROWSER_ORIGIN, - "x-forwarded-for": "203.0.113.50", - "x-forwarded-proto": "https", - "x-forwarded-user": "operator@example.com", + await withTrustedProxyBrowserWs(ALLOWED_BROWSER_ORIGIN, async (ws) => { + const payload = await connectOk(ws, { + client: TEST_OPERATOR_CLIENT, + device: null, }); - try { - const payload = await connectOk(ws, { - client: TEST_OPERATOR_CLIENT, - device: null, - }); - expect(payload.type).toBe("hello-ok"); - } finally { - ws.close(); - } + expect(payload.type).toBe("hello-ok"); }); }); test("preserves scopes for trusted-proxy non-control-ui browser sessions", async () => { - const { writeConfigFile } = await import("../config/config.js"); - await writeConfigFile({ - gateway: { - auth: { - mode: "trusted-proxy", - trustedProxy: { - userHeader: "x-forwarded-user", - requiredHeaders: ["x-forwarded-proto"], - }, - }, - trustedProxies: ["127.0.0.1"], - controlUi: { - allowedOrigins: [ALLOWED_BROWSER_ORIGIN], - }, - }, - }); - - await withGatewayServer(async ({ port }) => { - const ws = await openWs(port, { - origin: ALLOWED_BROWSER_ORIGIN, - "x-forwarded-for": "203.0.113.50", - "x-forwarded-proto": "https", - "x-forwarded-user": "operator@example.com", + await withTrustedProxyBrowserWs(ALLOWED_BROWSER_ORIGIN, async (ws) => { + const payload = await connectOk(ws, { + client: TEST_OPERATOR_CLIENT, + device: null, + scopes: ["operator.read"], }); - try { - const payload = await connectOk(ws, { - client: TEST_OPERATOR_CLIENT, - device: null, - scopes: ["operator.read"], - }); - expect(payload.type).toBe("hello-ok"); + expect(payload.type).toBe("hello-ok"); - const status = await rpcReq(ws, "status"); - expect(status.ok).toBe(true); - } finally { - ws.close(); - } + const status = await rpcReq(ws, "status"); + expect(status.ok).toBe(true); }); });