fix: preserve original host through forward auth
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/dev-server",
|
||||
"version": "0.2.21",
|
||||
"version": "0.2.22",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -135,11 +135,18 @@ export function forwardAuthFailure(res: Response, verifierUrl: string): Response
|
||||
/** Describe the original gateway request to a forward-auth verifier. */
|
||||
export function forwardAuthHeaders(req: Request): Headers {
|
||||
const original = new URL(req.url);
|
||||
const host = req.headers.get("host") ?? original.host;
|
||||
const protocol = original.protocol.replace(":", "");
|
||||
return new Headers({
|
||||
cookie: req.headers.get("cookie") ?? "",
|
||||
authorization: req.headers.get("authorization") ?? "",
|
||||
"x-forwarded-host": req.headers.get("host") ?? original.host,
|
||||
"x-forwarded-proto": original.protocol.replace(":", ""),
|
||||
"x-forwarded-host": host,
|
||||
"x-forwarded-proto": protocol,
|
||||
// These survive when a verifier such as sso.localhost is routed through
|
||||
// this gateway again. The second hop may replace X-Forwarded-Host with the
|
||||
// verifier host, but must not lose the protected application's return URL.
|
||||
"x-original-host": host,
|
||||
"x-original-proto": protocol,
|
||||
"x-original-method": req.method,
|
||||
"x-original-uri": `${original.pathname}${original.search}`,
|
||||
});
|
||||
|
||||
@@ -52,12 +52,37 @@ test("forward auth describes the original gateway request", () => {
|
||||
|
||||
expect(headers.get("x-forwarded-host")).toBe("admin.example.test");
|
||||
expect(headers.get("x-forwarded-proto")).toBe("https");
|
||||
expect(headers.get("x-original-host")).toBe("admin.example.test");
|
||||
expect(headers.get("x-original-proto")).toBe("https");
|
||||
expect(headers.get("x-original-method")).toBe("GET");
|
||||
expect(headers.get("x-original-uri")).toBe("/settings?tab=security");
|
||||
expect(headers.get("cookie")).toBe("session=abc");
|
||||
expect(headers.get("authorization")).toBe("Bearer token");
|
||||
});
|
||||
|
||||
test("nested SSO proxy keeps the protected app's original request headers", () => {
|
||||
const authHeaders = forwardAuthHeaders(
|
||||
new Request("http://admin.localhost:3000/settings", {
|
||||
headers: { host: "admin.localhost:3000" },
|
||||
}),
|
||||
);
|
||||
authHeaders.set("host", "sso.localhost:3000");
|
||||
const verifierRequest = new Request("http://sso.localhost:3000/api/verify", {
|
||||
headers: authHeaders,
|
||||
});
|
||||
|
||||
const proxied = gatewayProxyHeaders(
|
||||
verifierRequest,
|
||||
new URL(verifierRequest.url),
|
||||
"127.0.0.1",
|
||||
true,
|
||||
);
|
||||
|
||||
expect(proxied.get("x-forwarded-host")).toBe("sso.localhost:3000");
|
||||
expect(proxied.get("x-original-host")).toBe("admin.localhost:3000");
|
||||
expect(proxied.get("x-original-uri")).toBe("/settings");
|
||||
});
|
||||
|
||||
test("gateway respawns development apps after an HMR restart exit", () => {
|
||||
expect(gatewayRestartDelay("development", 97, null)).toBe(0);
|
||||
expect(gatewayRestartDelay("development", 1, null)).toBe(1200);
|
||||
|
||||
Reference in New Issue
Block a user