better-auth
Version:
The most comprehensive authentication framework for TypeScript.
54 lines (53 loc) • 2.74 kB
JavaScript
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 };