import { getAuthSessionSecret, isAuthEnabled, SESSION_COOKIE, SESSION_MAX_AGE_SEC, } from "@/lib/auth/config"; const encoder = new TextEncoder(); async function hmacHex(payload: string, secret: string): Promise { const key = await crypto.subtle.importKey( "raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"], ); const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(payload)); return Array.from(new Uint8Array(sig)) .map((b) => b.toString(16).padStart(2, "0")) .join(""); } export async function createSessionToken(username: string): Promise { const exp = Date.now() + SESSION_MAX_AGE_SEC * 1000; const payload = `${exp}:${username}`; const sig = await hmacHex(payload, getAuthSessionSecret()); return `${payload}:${sig}`; } export async function verifySessionToken(token: string): Promise { if (!isAuthEnabled()) { return true; } const parts = token.split(":"); if (parts.length < 3) { return false; } const sig = parts.pop()!; const username = parts.pop()!; const exp = Number(parts.join(":")); if (!Number.isFinite(exp) || exp < Date.now()) { return false; } const payload = `${exp}:${username}`; const expected = await hmacHex(payload, getAuthSessionSecret()); return sig === expected; } export async function getSessionUsername( token: string | undefined, ): Promise { if (!isAuthEnabled()) { return "guest"; } if (!token || !(await verifySessionToken(token))) { return null; } const parts = token.split(":"); if (parts.length < 3) { return null; } return parts[parts.length - 2] ?? null; } export { SESSION_COOKIE, SESSION_MAX_AGE_SEC };