Putting secrets into environment variables is problematic due to them being inherited by sub-processes, the ease as which these can be leaked in logs, and the lack of support for loading secrets into environment variables by systems such as systemd and docker. Change the loading of secrets to be done by loading the content of a file specified by an environment variable.
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import type { H3Event } from "h3";
|
|
import * as fs from "node:fs/promises";
|
|
|
|
let cachedCookieSecret: CryptoKey;
|
|
export async function useCookieSecret(event: H3Event) {
|
|
if (cachedCookieSecret)
|
|
return cachedCookieSecret;
|
|
|
|
const runtimeConfig = useRuntimeConfig(event);
|
|
if (!runtimeConfig.cookieSecretKeyFile) throw new Error("NUXT_COOKIE_SECRET_KEY_FILE not set.");
|
|
return cachedCookieSecret = await crypto.subtle.importKey(
|
|
"raw",
|
|
Buffer.from(await fs.readFile(runtimeConfig.cookieSecretKeyFile, "utf-8"), "base64url"),
|
|
{ name: "HMAC", hash: "SHA-256" },
|
|
false,
|
|
["sign", "verify"],
|
|
);
|
|
}
|
|
|
|
export async function setSignedCookie(event: H3Event, name: string, value: string, maxAge?: number) {
|
|
const secret = await useCookieSecret(event);
|
|
const signature = await crypto.subtle.sign("HMAC", secret, Buffer.from(`${name}=${value}`));
|
|
const cookie = `${value}.${Buffer.from(signature).toString("base64url")}`
|
|
setCookie(event, name, cookie, { httpOnly: true, secure: true, sameSite: true, maxAge });
|
|
}
|
|
|
|
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(`${name}=${value}`));
|
|
if (!valid)
|
|
return
|
|
|
|
return value;
|
|
}
|