nuxt
Version:
42 lines (41 loc) • 2.04 kB
JavaScript
import { createError } from "../app/error.js";
import { useRuntimeConfig } from "nuxt/internal/server-runtime-config";
//#region src/server/secret.ts
const MIN_LENGTH = 32;
const SALT = new TextEncoder().encode("nuxt");
let warnedGenerated = false;
/**
* A secret for one purpose, derived from `appSecret` with HKDF-SHA256: 32 bytes,
* hex-encoded. Stable while `appSecret` is unchanged; distinct for every purpose.
* Namespace the purpose to what owns it, such as a module name.
*
* @example
* ```ts
* const password = await deriveSecret('nuxt-auth-utils:session')
* ```
*
* @throws a `500` when `appSecret` is unset or shorter than 32 characters.
* @since 4.6.0
*/
async function deriveSecret(purpose) {
const root = useRuntimeConfig().appSecret;
if (typeof root !== "string" || root.length < MIN_LENGTH) throw createError({
status: 500,
message: root !== void 0 && root !== "" && typeof root !== "string" ? `\`appSecret\` was set to a ${Array.isArray(root) ? "array" : typeof root}, because Nitro parses environment overrides. Quote the value (\`NUXT_APP_SECRET='"…"'\`) or set \`runtimeConfig.appSecret\` in \`nuxt.config\`.` : `\`appSecret\` is not set. Set \`NUXT_APP_SECRET\` to at least ${MIN_LENGTH} characters, or pass a secret explicitly.`
});
if (import.meta.dev && !warnedGenerated && globalThis.process?.env?.NUXT_APP_SECRET_GENERATED === "1") {
warnedGenerated = true;
console.warn("[nuxt] [NUXT_B5028] A generated development `appSecret` is being used. Set `NUXT_APP_SECRET` in your `.env` to the output of `openssl rand -base64 32`. Builds do not generate a secret.");
}
const encoder = new TextEncoder();
const key = await globalThis.crypto.subtle.importKey("raw", encoder.encode(root), "HKDF", false, ["deriveBits"]);
const bits = await globalThis.crypto.subtle.deriveBits({
name: "HKDF",
hash: "SHA-256",
salt: SALT,
info: encoder.encode(purpose)
}, key, 256);
return [...new Uint8Array(bits)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}
//#endregion
export { deriveSecret };