BT  ·  2026-10-10

auth.ts

 1/** Checks HTTP basic auth against the AUTH_USER / AUTH_PASS secrets. Fails closed if unset. */
 2export async function isAuthorized(req: Request, env: Env): Promise<boolean> {
 3  if (!env.AUTH_USER || !env.AUTH_PASS) return false;
 4  const header = req.headers.get("authorization") ?? "";
 5  const match = header.match(/^Basic\s+(.+)$/i);
 6  if (!match) return false;
 7  let supplied: string;
 8  try {
 9    supplied = atob(match[1]);
10  } catch {
11    return false;
12  }
13  // Compare fixed-length digests so timingSafeEqual never sees mismatched lengths.
14  const [a, b] = await Promise.all([digest(supplied), digest(`${env.AUTH_USER}:${env.AUTH_PASS}`)]);
15  return crypto.subtle.timingSafeEqual(a, b);
16}
17
18async function digest(s: string): Promise<ArrayBuffer> {
19  return crypto.subtle.digest("SHA-256", new TextEncoder().encode(s));
20}
21
22export function unauthorized(): Response {
23  return new Response("Authentication required", {
24    status: 401,
25    headers: { "www-authenticate": 'Basic realm="monitor", charset="UTF-8"' },
26  });
27}