feat: add helpers and improve workspace auth flows

This commit is contained in:
2026-07-13 13:53:36 +05:30
parent 88e907783a
commit b4e5fade19
74 changed files with 853 additions and 131 deletions
+31 -8
View File
@@ -103,6 +103,35 @@ function timingSafeEqual(a: string, b: string): boolean {
return diff === 0;
}
/** Preserve an intentional verifier redirect while keeping other failures opaque. */
export function forwardAuthFailure(res: Response, verifierUrl: string): Response {
const location = res.headers.get("location");
if (res.status >= 300 && res.status < 400 && location) {
try {
const redirect = new URL(location, verifierUrl);
if (redirect.protocol === "http:" || redirect.protocol === "https:") {
return new Response(null, { status: res.status, headers: { location: redirect.href } });
}
} catch {
// Malformed or unsafe redirects fail closed below.
}
}
return new Response("Unauthorized", { status: res.status === 200 ? 401 : res.status });
}
/** Describe the original gateway request to a forward-auth verifier. */
export function forwardAuthHeaders(req: Request): Headers {
const original = new URL(req.url);
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-original-method": req.method,
"x-original-uri": `${original.pathname}${original.search}`,
});
}
/**
* Enforce a per-app auth policy. Returns a Response to block, or null to allow.
* `ip` is the client address (for the IP allowlist).
@@ -140,16 +169,10 @@ async function checkAuth(
if (auth.forward) {
try {
const res = await fetch(auth.forward.url, {
headers: {
cookie: req.headers.get("cookie") ?? "",
authorization: req.headers.get("authorization") ?? "",
"x-forwarded-host": req.headers.get("host") ?? "",
"x-original-uri": new URL(req.url).pathname,
},
headers: forwardAuthHeaders(req),
redirect: "manual",
});
if (!res.ok)
return new Response("Unauthorized", { status: res.status === 200 ? 401 : res.status });
if (!res.ok) return forwardAuthFailure(res, auth.forward.url);
} catch {
return new Response("Auth service unavailable", { status: 503 });
}