Gateway: preserve trusted-proxy browser scopes

This commit is contained in:
Vincent Koc
2026-03-12 14:56:40 -04:00
parent b2e21e3792
commit 8661c271e9
2 changed files with 43 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ import {
connectOk,
installGatewayTestHooks,
readConnectChallengeNonce,
rpcReq,
testState,
trackConnectChallengeNonce,
withGatewayServer,
@@ -150,6 +151,47 @@ describe("gateway auth browser hardening", () => {
});
});
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",
});
try {
const payload = await connectOk(ws, {
client: TEST_OPERATOR_CLIENT,
device: null,
scopes: ["operator.read"],
});
expect(payload.type).toBe("hello-ok");
const status = await rpcReq(ws, "status");
expect(status.ok).toBe(true);
} finally {
ws.close();
}
});
});
test.each([
{
name: "rejects disallowed origins",

View File

@@ -526,7 +526,7 @@ export function attachGatewayWsMessageHandler(params: {
hasSharedAuth,
isLocalClient,
});
if (!device && (!isControlUi || decision.kind !== "allow")) {
if (!device && decision.kind !== "allow") {
clearUnboundScopes();
}
if (decision.kind === "allow") {