import { env } from "cloudflare:workers";
import { cookieValue } from "../auth";
import { decryptSecret, hmacSha256Hex, randomToken, sha256Hex, timingSafeEqualStrings } from "../crypto";
import { enforceRateLimit, requestIp } from "../limits";
import { codeKey, cookieSecret, SITE_LIMITS } from "./config";
import { safeNext, signAccess, verifyAccess } from "./naming";
import { verifySitePassword } from "./password";
import { finishOidc, startOidc } from "./oidc";
import { html, plain } from "./static";
import type { SiteMeta } from "./config";
export const LOGIN_PATH = "/__gitfor/login";
export const CALLBACK_PATH = "/__gitfor/callback";
const LOGOUT_PATH = "/__gitfor/logout";
const STATE_SECONDS = 600;
type CodeRecord = { siteId: string; host: string; subject: string };
function secure(url: URL): boolean {
return url.protocol === "https:";
}
function name(url: URL, base: string): string {
return secure(url) ? `__Host-${base}` : base;
}
/** Host-only (no Domain), so the cookie is never shared with the forge or sibling sites. */
function setCookie(url: URL, base: string, value: string, maxAge: number): string {
return `${name(url, base)}=${encodeURIComponent(value)}; Path=/; HttpOnly;${secure(url) ? " Secure;" : ""} SameSite=Lax; Max-Age=${maxAge}`;
}
function redirect(location: string, cookies: string[] = []): Response {
const headers = new Headers({ location, "cache-control": "no-store" });
for (const cookie of cookies) headers.append("set-cookie", cookie);
return new Response(null, { status: 303, headers });
}
/** The verified visitor for this site and host, or null. Public sites never need a cookie. */
export async function accessSubject(request: Request, meta: SiteMeta): Promise<string | null> {
const url = new URL(request.url);