Skip to content

Commit 776331f

Browse files
authored
fix: consider NUXT_BETTER_AUTH_SECRET for env validation (#271)
1 parent 914cd86 commit 776331f

File tree

12 files changed

+167
-63
lines changed

12 files changed

+167
-63
lines changed

docs/app/components/GenerateSecret.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ function generate() {
2121
for (const block of codeBlocks) {
2222
const spans = block.querySelectorAll('span.line span')
2323
for (const span of spans) {
24-
if (span.textContent?.includes('BETTER_AUTH_SECRET=')) {
25-
span.textContent = `BETTER_AUTH_SECRET=${secretValue.value}`
24+
if (span.textContent?.includes('NUXT_BETTER_AUTH_SECRET=')) {
25+
span.textContent = `NUXT_BETTER_AUTH_SECRET=${secretValue.value}`
2626
// Hide copy button on this code block
2727
const pre = block.closest('pre')
2828
const copyBtn = pre?.querySelector('button')
@@ -37,8 +37,8 @@ function generate() {
3737
for (const block of codeBlocks) {
3838
const spans = block.querySelectorAll('span.line span')
3939
for (const span of spans) {
40-
if (span.textContent?.includes('BETTER_AUTH_SECRET=')) {
41-
span.textContent = 'BETTER_AUTH_SECRET='
40+
if (span.textContent?.includes('NUXT_BETTER_AUTH_SECRET=')) {
41+
span.textContent = 'NUXT_BETTER_AUTH_SECRET='
4242
// Restore copy button
4343
const pre = block.closest('pre')
4444
const copyBtn = pre?.querySelector('button')
@@ -56,7 +56,7 @@ function generate() {
5656
5757
async function copySecret() {
5858
if (secretValue.value) {
59-
await copy(`BETTER_AUTH_SECRET=${secretValue.value}`)
59+
await copy(`NUXT_BETTER_AUTH_SECRET=${secretValue.value}`)
6060
copied.value = true
6161
toast.add({ title: 'Copied to clipboard', icon: 'i-lucide-check', color: 'success' })
6262
}

docs/content/1.getting-started/0.index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export default defineNuxtConfig({
7070
```
7171

7272
```ini [.env]
73-
BETTER_AUTH_SECRET="generate-a-32-char-secret"
73+
NUXT_BETTER_AUTH_SECRET="generate-a-32-char-secret"
7474
```
7575

7676
### Create Config Files

docs/content/1.getting-started/1.installation.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ npx nuxi module add @onmax/nuxt-better-auth@alpha
2121
### Set Environment Variables
2222

2323
::tip{icon="i-lucide-sparkles"}
24-
When you install the module with `nuxi module add`, it prompts you to generate `BETTER_AUTH_SECRET` and can append it to your `.env`. In CI/test environments it auto-generates the secret.
24+
When you install the module with `nuxi module add`, it prompts you to generate `NUXT_BETTER_AUTH_SECRET` and can append it to your `.env`. `BETTER_AUTH_SECRET` still works as a compatibility fallback. In CI/test environments it auto-generates the secret.
2525
::
2626

2727
Add these environment variables to `.env`:
@@ -31,7 +31,7 @@ Add these environment variables to `.env`:
3131
The secret encrypts and hashes sensitive data. Must be at least 32 characters with high entropy.
3232

3333
```txt [.env]
34-
BETTER_AUTH_SECRET=
34+
NUXT_BETTER_AUTH_SECRET=
3535
```
3636

3737
::generate-secret
@@ -44,7 +44,7 @@ openssl rand -base64 32
4444
```
4545

4646
::tip
47-
Prefix the variable with `NUXT_` to use Nuxt's runtime config system (recommended for multi-environment deployments): `NUXT_BETTER_AUTH_SECRET=`
47+
Use `NUXT_BETTER_AUTH_SECRET` for Nuxt runtime config and multi-environment deployments. `BETTER_AUTH_SECRET` remains supported as a fallback.
4848
::
4949

5050
2. **Base URL** (Optional)

docs/content/1.getting-started/2.configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,12 @@ The module can auto-detect the request URL on most deployments. You should still
237237
Configure secrets using environment variables (see [Installation](/getting-started/installation#set-environment-variables)).
238238

239239
```ini [.env]
240-
BETTER_AUTH_SECRET="your-super-secret-key"
240+
NUXT_BETTER_AUTH_SECRET="your-super-secret-key"
241241
NUXT_PUBLIC_SITE_URL="https://your-domain.com" # Optional on Vercel/Cloudflare/Netlify
242242
```
243243

244244
::tip
245-
Prefix the variable with `NUXT_` to use Nuxt's runtime config system (recommended for multi-environment deployments): `NUXT_BETTER_AUTH_SECRET=`
245+
Use `NUXT_BETTER_AUTH_SECRET` as the primary secret variable. `BETTER_AUTH_SECRET` remains supported as a fallback for existing setups.
246246
::
247247

248248
## For Module Authors

docs/content/3.guides/4.database-less-mode.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ See the official **Better Auth documentation** for database-less setup.
1212
Database-less mode uses **JWE (JSON Web Encryption)** sessions. Instead of storing sessions in a database, the session data is encrypted and stored entirely in the cookie.
1313

1414
**How it works:**
15-
- Session data is encrypted with your `BETTER_AUTH_SECRET`
15+
- Session data is encrypted with your `NUXT_BETTER_AUTH_SECRET` (`BETTER_AUTH_SECRET` is also supported as a fallback)
1616
- The encrypted token is stored in a cookie
1717
- On each request, the server decrypts the cookie to get session data
1818
- No database queries needed for session validation

docs/content/3.guides/9.production-deployment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,9 @@ export default defineNuxtConfig({
115115

116116
## Common Issues
117117

118-
### "BETTER_AUTH_SECRET must be at least 32 characters"
118+
### "NUXT_BETTER_AUTH_SECRET must be at least 32 characters"
119119

120-
Your secret is too short. Generate a new one using the command above.
120+
Your secret is too short. Generate a new one using the command above. `BETTER_AUTH_SECRET` is still accepted as a fallback, but `NUXT_BETTER_AUTH_SECRET` is the recommended variable.
121121

122122
### "siteUrl required in production"
123123

docs/public/.well-known/skills/nuxt-better-auth/references/installation.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ export default defineNuxtConfig({
3434

3535
```bash
3636
# Required (min 32 chars)
37-
BETTER_AUTH_SECRET=your-secret-key-at-least-32-characters
37+
NUXT_BETTER_AUTH_SECRET=your-secret-key-at-least-32-characters
38+
# Legacy fallback also supported: BETTER_AUTH_SECRET=your-secret-key-at-least-32-characters
3839

3940
# Required in production for OAuth
4041
NUXT_PUBLIC_SITE_URL=https://your-domain.com

src/module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default defineNuxtModule<BetterAuthModuleOptions>({
7777
const configuredSecret = nuxt.options.runtimeConfig?.betterAuthSecret as string | undefined
7878
const generatedSecret = await promptForSecret(nuxt.options.rootDir, consola, { configuredSecret, prepare: Boolean(nuxt.options._prepare) })
7979
if (generatedSecret)
80-
process.env.BETTER_AUTH_SECRET = generatedSecret
80+
process.env.NUXT_BETTER_AUTH_SECRET = generatedSecret
8181

8282
await createDefaultAuthConfigFiles(nuxt)
8383
},

src/module/runtime.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@ export function setupRuntimeConfig(input: SetupRuntimeConfigInput): { useHubKV:
6666
}
6767

6868
const currentSecret = nuxt.options.runtimeConfig.betterAuthSecret as string | undefined
69-
nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.BETTER_AUTH_SECRET || ''
69+
nuxt.options.runtimeConfig.betterAuthSecret = currentSecret || process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || ''
7070

7171
const betterAuthSecret = nuxt.options.runtimeConfig.betterAuthSecret as string
7272
if (!nuxt.options.dev && !nuxt.options._prepare && !betterAuthSecret) {
73-
throw new Error('[nuxt-better-auth] BETTER_AUTH_SECRET is required in production. Set BETTER_AUTH_SECRET or NUXT_BETTER_AUTH_SECRET environment variable.')
73+
throw new Error('[nuxt-better-auth] NUXT_BETTER_AUTH_SECRET is required in production. Set NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET environment variable.')
7474
}
7575
if (betterAuthSecret && betterAuthSecret.length < 32) {
76-
throw new Error('[nuxt-better-auth] BETTER_AUTH_SECRET must be at least 32 characters for security')
76+
throw new Error('[nuxt-better-auth] NUXT_BETTER_AUTH_SECRET must be at least 32 characters for security')
7777
}
7878

7979
nuxt.options.runtimeConfig.auth = defu(nuxt.options.runtimeConfig.auth as Record<string, unknown>, {

src/module/secret.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
44
import { join } from 'pathe'
55
import { isCI, isTest } from 'std-env'
66

7+
const DEFAULT_SECRET_ENV = 'NUXT_BETTER_AUTH_SECRET'
8+
const FALLBACK_SECRET_ENV = 'BETTER_AUTH_SECRET'
9+
710
const generateSecret = () => randomBytes(32).toString('hex')
811

912
function readEnvFile(rootDir: string): string {
@@ -12,16 +15,19 @@ function readEnvFile(rootDir: string): string {
1215
}
1316

1417
function hasEnvSecret(rootDir: string): boolean {
15-
const match = readEnvFile(rootDir).match(/^BETTER_AUTH_SECRET=(.+)$/m)
16-
return !!match && !!match[1] && match[1].trim().length > 0
18+
const envFile = readEnvFile(rootDir)
19+
return [DEFAULT_SECRET_ENV, FALLBACK_SECRET_ENV].some((name) => {
20+
const match = envFile.match(new RegExp(`^${name}=(.+)$`, 'm'))
21+
return !!match && !!match[1] && match[1].trim().length > 0
22+
})
1723
}
1824

1925
function appendSecretToEnv(rootDir: string, secret: string): void {
2026
const envPath = join(rootDir, '.env')
2127
let content = readEnvFile(rootDir)
2228
if (content.length > 0 && !content.endsWith('\n'))
2329
content += '\n'
24-
content += `BETTER_AUTH_SECRET=${secret}\n`
30+
content += `${DEFAULT_SECRET_ENV}=${secret}\n`
2531
writeFileSync(envPath, content, 'utf-8')
2632
}
2733

@@ -35,23 +41,23 @@ export async function promptForSecret(rootDir: string, consola: ConsolaInstance,
3541
if (configuredSecret)
3642
return undefined
3743

38-
if (process.env.BETTER_AUTH_SECRET || hasEnvSecret(rootDir))
44+
if (process.env.NUXT_BETTER_AUTH_SECRET || process.env.BETTER_AUTH_SECRET || hasEnvSecret(rootDir))
3945
return undefined
4046

4147
const hasTty = Boolean(process.stdin.isTTY && process.stdout.isTTY)
4248
if (options.prepare || !hasTty) {
43-
consola.warn('[nuxt-better-auth] Skipping BETTER_AUTH_SECRET prompt (non-interactive). Set BETTER_AUTH_SECRET or NUXT_BETTER_AUTH_SECRET.')
49+
consola.warn('[nuxt-better-auth] Skipping NUXT_BETTER_AUTH_SECRET prompt (non-interactive). Set NUXT_BETTER_AUTH_SECRET or BETTER_AUTH_SECRET.')
4450
return undefined
4551
}
4652

4753
if (isCI || isTest) {
4854
const secret = generateSecret()
4955
appendSecretToEnv(rootDir, secret)
50-
consola.info('Generated BETTER_AUTH_SECRET and added to .env (CI/test mode)')
56+
consola.info('Generated NUXT_BETTER_AUTH_SECRET and added to .env (CI/test mode)')
5157
return secret
5258
}
5359

54-
consola.box('BETTER_AUTH_SECRET is required for authentication.\nThis will be appended to your .env file.')
60+
consola.box('NUXT_BETTER_AUTH_SECRET is required for authentication.\nThis will be appended to your .env file.\nBETTER_AUTH_SECRET is still supported as a fallback.')
5561
const choice = await consola.prompt('How do you want to set it?', {
5662
type: 'select',
5763
options: [
@@ -63,7 +69,7 @@ export async function promptForSecret(rootDir: string, consola: ConsolaInstance,
6369
}) as 'generate' | 'paste' | 'skip' | symbol
6470

6571
if (typeof choice === 'symbol' || choice === 'skip') {
66-
consola.warn('Skipping BETTER_AUTH_SECRET. Auth will fail without it in production.')
72+
consola.warn('Skipping NUXT_BETTER_AUTH_SECRET. Auth will fail without it in production.')
6773
return undefined
6874
}
6975

@@ -81,13 +87,13 @@ export async function promptForSecret(rootDir: string, consola: ConsolaInstance,
8187
}
8288

8389
const preview = `${secret.slice(0, 8)}...${secret.slice(-4)}`
84-
const confirm = await consola.prompt(`Add to .env:\nBETTER_AUTH_SECRET=${preview}\nProceed?`, { type: 'confirm', initial: true, cancel: 'null' }) as boolean | symbol
90+
const confirm = await consola.prompt(`Add to .env:\n${DEFAULT_SECRET_ENV}=${preview}\nProceed?`, { type: 'confirm', initial: true, cancel: 'null' }) as boolean | symbol
8591
if (typeof confirm === 'symbol' || !confirm) {
8692
consola.info('Cancelled. Secret not written.')
8793
return undefined
8894
}
8995

9096
appendSecretToEnv(rootDir, secret)
91-
consola.success('Added BETTER_AUTH_SECRET to .env')
97+
consola.success('Added NUXT_BETTER_AUTH_SECRET to .env')
9298
return secret
9399
}

0 commit comments

Comments
 (0)