Skip to content

Commit 8661c27

Browse files
committed
Gateway: preserve trusted-proxy browser scopes
1 parent b2e21e3 commit 8661c27

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/gateway/server.auth.browser-hardening.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
connectOk,
1616
installGatewayTestHooks,
1717
readConnectChallengeNonce,
18+
rpcReq,
1819
testState,
1920
trackConnectChallengeNonce,
2021
withGatewayServer,
@@ -150,6 +151,47 @@ describe("gateway auth browser hardening", () => {
150151
});
151152
});
152153

154+
test("preserves scopes for trusted-proxy non-control-ui browser sessions", async () => {
155+
const { writeConfigFile } = await import("../config/config.js");
156+
await writeConfigFile({
157+
gateway: {
158+
auth: {
159+
mode: "trusted-proxy",
160+
trustedProxy: {
161+
userHeader: "x-forwarded-user",
162+
requiredHeaders: ["x-forwarded-proto"],
163+
},
164+
},
165+
trustedProxies: ["127.0.0.1"],
166+
controlUi: {
167+
allowedOrigins: [ALLOWED_BROWSER_ORIGIN],
168+
},
169+
},
170+
});
171+
172+
await withGatewayServer(async ({ port }) => {
173+
const ws = await openWs(port, {
174+
origin: ALLOWED_BROWSER_ORIGIN,
175+
"x-forwarded-for": "203.0.113.50",
176+
"x-forwarded-proto": "https",
177+
"x-forwarded-user": "[email protected]",
178+
});
179+
try {
180+
const payload = await connectOk(ws, {
181+
client: TEST_OPERATOR_CLIENT,
182+
device: null,
183+
scopes: ["operator.read"],
184+
});
185+
expect(payload.type).toBe("hello-ok");
186+
187+
const status = await rpcReq(ws, "status");
188+
expect(status.ok).toBe(true);
189+
} finally {
190+
ws.close();
191+
}
192+
});
193+
});
194+
153195
test.each([
154196
{
155197
name: "rejects disallowed origins",

src/gateway/server/ws-connection/message-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ export function attachGatewayWsMessageHandler(params: {
526526
hasSharedAuth,
527527
isLocalClient,
528528
});
529-
if (!device && (!isControlUi || decision.kind !== "allow")) {
529+
if (!device && decision.kind !== "allow") {
530530
clearUnboundScopes();
531531
}
532532
if (decision.kind === "allow") {

0 commit comments

Comments
 (0)