UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

54 lines (53 loc) 2.74 kB
import "../utils/constants.mjs"; import { BetterAuthError } from "@better-auth/core/error"; //#region src/context/secret-utils.ts /** * Estimates the entropy of a string in bits. * This is a simple approximation that helps detect low-entropy secrets. */ function estimateEntropy(str) { const unique = new Set(str).size; if (unique === 0) return 0; return Math.log2(Math.pow(unique, str.length)); } function parseSecretsEnv(envValue) { if (!envValue) return null; return envValue.split(",").map((entry) => { entry = entry.trim(); const colonIdx = entry.indexOf(":"); if (colonIdx === -1) throw new BetterAuthError(`Invalid BETTER_AUTH_SECRETS entry: "${entry}". Expected format: "<version>:<secret>"`); const version = parseInt(entry.slice(0, colonIdx), 10); if (!Number.isInteger(version) || version < 0) throw new BetterAuthError(`Invalid version in BETTER_AUTH_SECRETS: "${entry.slice(0, colonIdx)}". Version must be a non-negative integer.`); const value = entry.slice(colonIdx + 1).trim(); if (!value) throw new BetterAuthError(`Empty secret value for version ${version} in BETTER_AUTH_SECRETS.`); return { version, value }; }); } function validateSecretsArray(secrets, logger) { if (secrets.length === 0) throw new BetterAuthError("`secrets` array must contain at least one entry."); const seen = /* @__PURE__ */ new Set(); for (const s of secrets) { const version = parseInt(String(s.version), 10); if (!Number.isInteger(version) || version < 0 || String(version) !== String(s.version).trim()) throw new BetterAuthError(`Invalid version ${s.version} in \`secrets\`. Version must be a non-negative integer.`); if (!s.value) throw new BetterAuthError(`Empty secret value for version ${version} in \`secrets\`.`); if (seen.has(version)) throw new BetterAuthError(`Duplicate version ${version} in \`secrets\`. Each version must be unique.`); seen.add(version); } const current = secrets[0]; if (current.value.length < 32) logger.warn(`[better-auth] Warning: the current secret (version ${current.version}) should be at least 32 characters long for adequate security.`); if (estimateEntropy(current.value) < 120) logger.warn("[better-auth] Warning: the current secret appears low-entropy. Use a randomly generated secret for production."); } function buildSecretConfig(secrets, legacySecret) { const keys = /* @__PURE__ */ new Map(); for (const s of secrets) keys.set(parseInt(String(s.version), 10), s.value); return { keys, currentVersion: parseInt(String(secrets[0].version), 10), legacySecret: legacySecret && legacySecret !== "better-auth-secret-12345678901234567890" ? legacySecret : void 0 }; } //#endregion export { buildSecretConfig, parseSecretsEnv, validateSecretsArray };