refactor: share browser auth test helpers

This commit is contained in:
Peter Steinberger 2026-03-13 18:32:30 +00:00
parent 03c2814124
commit 389de66b25
1 changed files with 57 additions and 99 deletions

View File

@ -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<void>) {
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);
});
});