import type { H3Event } from "h3"; let cachedCookieSecret: CryptoKey; export async function useCookieSecret(event: H3Event) { if (cachedCookieSecret) return cachedCookieSecret; const runtimeConfig = useRuntimeConfig(event); return cachedCookieSecret = await crypto.subtle.importKey( "raw", Buffer.from(runtimeConfig.cookieSecretKey, "base64url"), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"], ); } export async function setSignedCookie(event: H3Event, name: string, value: string) { const secret = await useCookieSecret(event); const signature = await crypto.subtle.sign("HMAC", secret, Buffer.from(value)); const cookie = `${value}.${Buffer.from(signature).toString("base64url")}` setCookie(event, name, cookie, { httpOnly: true, secure: true, sameSite: true }); } export async function getSignedCookie(event: H3Event, name: string) { const cookie = getCookie(event, name); if (!cookie) return; const rightDot = cookie.lastIndexOf("."); if (rightDot === -1) return; const value = cookie.slice(0, rightDot); const secret = await useCookieSecret(event); const signature = Buffer.from(cookie.slice(rightDot + 1), "base64url"); const valid = await crypto.subtle.verify("HMAC", secret, signature, Buffer.from(value)); if (!valid) return return value; }