import { env } from "cloudflare:workers";
import { z } from "zod";
import { emailAllowed, isBlockedOutbound } from "./naming";
import { isForgeHostname, sitesDomain } from "./config";
import type { SiteMeta } from "./config";
type OidcConfig = NonNullable<SiteMeta["oidc"]>;
const DISCOVERY_CACHE_SECONDS = 3600;
const CLOCK_SKEW_SECONDS = 60;
const discoverySchema = z.object({
issuer: z.string(),
authorization_endpoint: z.string(),
token_endpoint: z.string(),
jwks_uri: z.string(),
});
type Discovery = z.infer<typeof discoverySchema>;
const jwkSchema = z.object({ kid: z.string().optional(), kty: z.string(), alg: z.string().optional() }).passthrough();
const claimsSchema = z.object({
iss: z.string(),
aud: z.union([z.string(), z.array(z.string())]),
exp: z.number(),
nonce: z.string().optional(),
email: z.string().optional(),
email_verified: z.union([z.boolean(), z.string()]).optional(),
});
/** Only public HTTPS endpoints; a site owner must not be able to point the dispatcher at internal hosts. */
export function assertPublicHttps(raw: string): URL {
const url = new URL(raw);
const blocked = [new URL(env.PUBLIC_URL).hostname, sitesDomain()].filter((host): host is string => Boolean(host));
if (url.protocol !== "https:" || isBlockedOutbound(url, blocked) || isForgeHostname(url.hostname)) {
throw new Error(`OIDC endpoint ${url.hostname} must be a public https URL`);
}
return url;
}
async function getJson(url: string, init?: RequestInit): Promise<unknown> {