{"record":{"id":"f5f90797ae2769ab","repo":"gethomepage/homepage","slug":"homepage-auth-secret-or-nextauth-secret-must-be","errorCode":null,"errorMessage":"HOMEPAGE_AUTH_SECRET (or NEXTAUTH_SECRET) must be at least ${MIN_AUTH_SECRET_LENGTH} characters. Generate one with: openssl rand -base64 32","messagePattern":"HOMEPAGE_AUTH_SECRET \\(or NEXTAUTH_SECRET\\) must be at least (.+?) characters\\. Generate one with: openssl rand -base64 32","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/pages/api/auth/[...nextauth].js","lineNumber":70,"sourceCode":"    parsedAuthUrl.hash\n  ) {\n    throw new Error(\n      \"HOMEPAGE_EXTERNAL_URL (or NEXTAUTH_URL) must be an absolute HTTP(S) URL without credentials, query, or fragment.\",\n    );\n  }\n\n  if (hasOidcConfig) {\n    if (!process.env.NEXTAUTH_SECRET) {\n      throw new Error(\"OIDC auth is enabled but required settings are missing.\");\n    }\n  } else if (hasAnyOidcConfig) {\n    throw new Error(\"OIDC auth is enabled but required settings are missing.\");\n  } else if (!homepageAuthPassword || !process.env.NEXTAUTH_SECRET) {\n    throw new Error(\"Password auth is enabled but required settings are missing.\");\n  }\n\n  if (process.env.NEXTAUTH_SECRET.length < MIN_AUTH_SECRET_LENGTH) {\n    throw new Error(\n      `HOMEPAGE_AUTH_SECRET (or NEXTAUTH_SECRET) must be at least ${MIN_AUTH_SECRET_LENGTH} characters. Generate one with: openssl rand -base64 32`,\n    );\n  }\n}\n\n// Give fail2ban / CrowdSec etc something to match on\nfunction logFailedPasswordSignIn() {\n  createLogger(\"nextauth\").warn(\"Failed password sign-in attempt\");\n}\n\nlet providers = [];\nif (authEnabled) {\n  if (hasOidcConfig) {\n    providers = [\n      {\n        id: \"homepage-oidc\",\n        name: process.env.HOMEPAGE_OIDC_NAME || \"Homepage OIDC\",\n        type: \"oauth\",","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/gethomepage/homepage/blob/b6dca1ae033e613d8e692f9a161a3cc53a5a2857/src/pages/api/auth/[...nextauth].js#L52-L88","documentation":"Thrown when NEXTAUTH_SECRET is present but shorter than MIN_AUTH_SECRET_LENGTH (32 characters). Short secrets are brute-forceable, so Homepage enforces a minimum entropy floor before allowing auth to start.","triggerScenarios":"authEnabled is true, NEXTAUTH_SECRET is set and passed the earlier presence checks, but `process.env.NEXTAUTH_SECRET.length < 32`. Common with placeholder values like 'secret', 'changeme', or a 16-char hex.","commonSituations":"Operator hardcoded a weak dev secret; reused a short API key; truncated output of a secret generator; copy-paste lost characters; older deploy with a now-non-compliant secret.","solutions":["Generate a fresh secret: `openssl rand -base64 32` (produces ~44 chars).","Set it as NEXTAUTH_SECRET and restart.","If using a secret manager, ensure it emits at least 32 characters of high entropy.","Rotate any existing sessions after changing the secret."],"exampleFix":"// before\nNEXTAUTH_SECRET=changeme\n\n// after\nNEXTAUTH_SECRET=$(openssl rand -base64 32)","handlingStrategy":"validation","validationCode":"function assertSecretStrength(raw, min = 32) {\n  if (typeof raw !== 'string' || raw.length < min) {\n    throw new Error(`Secret must be at least ${min} chars. Generate: openssl rand -base64 32`);\n  }\n}\n// preflight:\nassertSecretStrength(process.env.NEXTAUTH_SECRET, 32);","typeGuard":"function isStrongSecret(v, min = 32) {\n  return typeof v === 'string' && v.length >= min;\n}","tryCatchPattern":null,"preventionTips":["Always generate secrets with `openssl rand -base64 32`.","Add a CI check that the configured secret meets the length floor.","Never commit a real secret; never use 'changeme'.","Rotate sessions after any secret change."],"tags":["auth","secret","configuration","security","startup"],"backgroundTag":null,"analyzedSha":"b6dca1ae033e613d8e692f9a161a3cc53a5a2857","analyzedAt":"2026-08-13T04:48:44.121Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}