{"version":3,"file":"secret-utils.mjs","names":[],"sources":["../../src/context/secret-utils.ts"],"sourcesContent":["import type { SecretConfig } from \"@better-auth/core\";\nimport type { createLogger } from \"@better-auth/core/env\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport { DEFAULT_SECRET } from \"../utils/constants\";\n\n/**\n * Estimates the entropy of a string in bits.\n * This is a simple approximation that helps detect low-entropy secrets.\n */\nfunction estimateEntropy(str: string): number {\n\tconst unique = new Set(str).size;\n\tif (unique === 0) return 0;\n\treturn Math.log2(Math.pow(unique, str.length));\n}\n\nexport function parseSecretsEnv(\n\tenvValue: string | undefined,\n): Array<{ version: number; value: string }> | null {\n\tif (!envValue) return null;\n\tconst entries = envValue.split(\",\").map((entry) => {\n\t\tentry = entry.trim();\n\t\tconst colonIdx = entry.indexOf(\":\");\n\t\tif (colonIdx === -1) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Invalid BETTER_AUTH_SECRETS entry: \"${entry}\". Expected format: \"<version>:<secret>\"`,\n\t\t\t);\n\t\t}\n\t\tconst version = parseInt(entry.slice(0, colonIdx), 10);\n\t\tif (!Number.isInteger(version) || version < 0) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Invalid version in BETTER_AUTH_SECRETS: \"${entry.slice(0, colonIdx)}\". Version must be a non-negative integer.`,\n\t\t\t);\n\t\t}\n\t\tconst value = entry.slice(colonIdx + 1).trim();\n\t\tif (!value) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Empty secret value for version ${version} in BETTER_AUTH_SECRETS.`,\n\t\t\t);\n\t\t}\n\t\treturn { version, value };\n\t});\n\treturn entries;\n}\n\nexport function validateSecretsArray(\n\tsecrets: Array<{ version: number; value: string }>,\n\tlogger: ReturnType<typeof createLogger>,\n): void {\n\tif (secrets.length === 0) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"`secrets` array must contain at least one entry.\",\n\t\t);\n\t}\n\tconst seen = new Set<number>();\n\tfor (const s of secrets) {\n\t\tconst version = parseInt(String(s.version), 10);\n\t\tif (\n\t\t\t!Number.isInteger(version) ||\n\t\t\tversion < 0 ||\n\t\t\tString(version) !== String(s.version).trim()\n\t\t) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Invalid version ${s.version} in \\`secrets\\`. Version must be a non-negative integer.`,\n\t\t\t);\n\t\t}\n\t\tif (!s.value) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Empty secret value for version ${version} in \\`secrets\\`.`,\n\t\t\t);\n\t\t}\n\t\tif (seen.has(version)) {\n\t\t\tthrow new BetterAuthError(\n\t\t\t\t`Duplicate version ${version} in \\`secrets\\`. Each version must be unique.`,\n\t\t\t);\n\t\t}\n\t\tseen.add(version);\n\t}\n\tconst current = secrets[0]!;\n\tif (current.value.length < 32) {\n\t\tlogger.warn(\n\t\t\t`[better-auth] Warning: the current secret (version ${current.version}) should be at least 32 characters long for adequate security.`,\n\t\t);\n\t}\n\tconst entropy = estimateEntropy(current.value);\n\tif (entropy < 120) {\n\t\tlogger.warn(\n\t\t\t\"[better-auth] Warning: the current secret appears low-entropy. Use a randomly generated secret for production.\",\n\t\t);\n\t}\n}\n\nexport function buildSecretConfig(\n\tsecrets: Array<{ version: number; value: string }>,\n\tlegacySecret: string,\n): SecretConfig {\n\tconst keys = new Map<number, string>();\n\tfor (const s of secrets) {\n\t\tkeys.set(parseInt(String(s.version), 10), s.value);\n\t}\n\treturn {\n\t\tkeys,\n\t\tcurrentVersion: parseInt(String(secrets[0]!.version), 10),\n\t\tlegacySecret:\n\t\t\tlegacySecret && legacySecret !== DEFAULT_SECRET\n\t\t\t\t? legacySecret\n\t\t\t\t: undefined,\n\t};\n}\n"],"mappings":";;;;;;;;AASA,SAAS,gBAAgB,KAAqB;CAC7C,MAAM,SAAS,IAAI,IAAI,IAAI,CAAC;AAC5B,KAAI,WAAW,EAAG,QAAO;AACzB,QAAO,KAAK,KAAK,KAAK,IAAI,QAAQ,IAAI,OAAO,CAAC;;AAG/C,SAAgB,gBACf,UACmD;AACnD,KAAI,CAAC,SAAU,QAAO;AAuBtB,QAtBgB,SAAS,MAAM,IAAI,CAAC,KAAK,UAAU;AAClD,UAAQ,MAAM,MAAM;EACpB,MAAM,WAAW,MAAM,QAAQ,IAAI;AACnC,MAAI,aAAa,GAChB,OAAM,IAAI,gBACT,uCAAuC,MAAM,0CAC7C;EAEF,MAAM,UAAU,SAAS,MAAM,MAAM,GAAG,SAAS,EAAE,GAAG;AACtD,MAAI,CAAC,OAAO,UAAU,QAAQ,IAAI,UAAU,EAC3C,OAAM,IAAI,gBACT,4CAA4C,MAAM,MAAM,GAAG,SAAS,CAAC,4CACrE;EAEF,MAAM,QAAQ,MAAM,MAAM,WAAW,EAAE,CAAC,MAAM;AAC9C,MAAI,CAAC,MACJ,OAAM,IAAI,gBACT,kCAAkC,QAAQ,0BAC1C;AAEF,SAAO;GAAE;GAAS;GAAO;GACxB;;AAIH,SAAgB,qBACf,SACA,QACO;AACP,KAAI,QAAQ,WAAW,EACtB,OAAM,IAAI,gBACT,mDACA;CAEF,MAAM,uBAAO,IAAI,KAAa;AAC9B,MAAK,MAAM,KAAK,SAAS;EACxB,MAAM,UAAU,SAAS,OAAO,EAAE,QAAQ,EAAE,GAAG;AAC/C,MACC,CAAC,OAAO,UAAU,QAAQ,IAC1B,UAAU,KACV,OAAO,QAAQ,KAAK,OAAO,EAAE,QAAQ,CAAC,MAAM,CAE5C,OAAM,IAAI,gBACT,mBAAmB,EAAE,QAAQ,0DAC7B;AAEF,MAAI,CAAC,EAAE,MACN,OAAM,IAAI,gBACT,kCAAkC,QAAQ,kBAC1C;AAEF,MAAI,KAAK,IAAI,QAAQ,CACpB,OAAM,IAAI,gBACT,qBAAqB,QAAQ,+CAC7B;AAEF,OAAK,IAAI,QAAQ;;CAElB,MAAM,UAAU,QAAQ;AACxB,KAAI,QAAQ,MAAM,SAAS,GAC1B,QAAO,KACN,sDAAsD,QAAQ,QAAQ,gEACtE;AAGF,KADgB,gBAAgB,QAAQ,MAAM,GAChC,IACb,QAAO,KACN,iHACA;;AAIH,SAAgB,kBACf,SACA,cACe;CACf,MAAM,uBAAO,IAAI,KAAqB;AACtC,MAAK,MAAM,KAAK,QACf,MAAK,IAAI,SAAS,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,MAAM;AAEnD,QAAO;EACN;EACA,gBAAgB,SAAS,OAAO,QAAQ,GAAI,QAAQ,EAAE,GAAG;EACzD,cACC,gBAAgB,iBAAiB,iBAC9B,eACA;EACJ"}