Configuration
Configure @onmax/nuxt-better-auth module options and server auth.
- In `nuxt.config.ts`, set `auth.redirects` (login, guest, authenticated, logout) and `auth.preserveRedirect`
- Use `routeRules` or `nitro.routeRules` to define per-route auth: `{ auth: { only: 'user', redirectTo: '/login' } }`
- In `server/auth.config.ts`, use `defineServerAuth` (object or function syntax) to configure plugins and providers
- The function syntax receives `ctx` with `runtimeConfig` and `db` (NuxtHub)
- The module auto-injects `secret` and `baseURL` — do not set them in defineServerAuth
- Base URL priority: runtimeConfig > request URL > platform env vars > localhost
- Set `NUXT_PUBLIC_SITE_URL` for custom domains or deterministic OAuth callbacks
Read more: https://better-auth.nuxt.dev/raw/getting-started/configuration.md
Source: https://github.com/nuxt-modules/better-auth
Module Configuration
export default defineNuxtConfig({
modules: ['@onmax/nuxt-better-auth'],
auth: {
redirects: {
login: '/login',
guest: '/',
// authenticated: '/app', // optional
// logout: '/goodbye', // optional
},
preserveRedirect: true,
redirectQueryKey: 'redirect',
},
routeRules: {
'/app/**': { auth: { only: 'user', redirectTo: '/login' } },
'/login': { auth: { only: 'guest', redirectTo: '/app' } },
},
})
routeRules or nitro.routeRules. The module supports both. If both are set, it uses nitro.routeRules.falseEnable client-only mode for external auth backends. When true:- Skips
server/auth.config.tsrequirement - Skips server-side setup (API handlers, middleware, schema generation, devtools)
- Skips secret validation
'server/auth.config'Path to the server auth config file, relative to the project root.'app/auth.config'Path to the client auth config file, relative to the project root.{ login: '/login', guest: '/' }Global redirect fallbacks:login: where to redirect unauthenticated usersguest: where to redirect authenticated users trying to access guest-only routesauthenticated: where to navigate after successful authenticatedsignIn/signUpwhen noonSuccesscallback is providedlogout: where to navigate after logout (no default)
redirectTo takes precedence when set.trueWhen redirecting unauthenticated users to a login route, append the original requested path as a query param.Configure redirect targets per-route with routeRules.auth.redirectTo or definePageMeta({ auth: { redirectTo } }).'redirect'Query param key used when preserveRedirect is enabled.falseEnable secondary storage for sessions, reducing database hits for session validation.true— Use NuxtHub KV. Requires NuxtHub Integration withhub: { kv: true }. Build fails if KV is not enabled. Generated schema remains stable and keeps core auth tables (user,account,session,verification).'custom'— You provide your ownsecondaryStorageindefineServerAuth()(required; the build fails in production if missing). The module won't inject NuxtHub KV, and this mode can omit thesessiontable from generated schema.false(default) — No secondary storage from the module. User-providedsecondaryStorageindefineServerAuth()is not overridden.
falsePluralize table names (user → users)camelCaseColumn/table name casing. Falls back to hub.db.casing when not specified.Redirect Targets (RouteRules-First)
Prefer redirect paths on route-level auth config:
export default defineNuxtConfig({
routeRules: {
'/app/**': { auth: { only: 'user', redirectTo: '/login' } },
'/login': { auth: { only: 'guest', redirectTo: '/app' } },
},
})
You can use the same auth route rules under nitro.routeRules:
export default defineNuxtConfig({
nitro: {
routeRules: {
'/app/**': { auth: { only: 'user', redirectTo: '/login' } },
'/login': { auth: { only: 'guest', redirectTo: '/app' } },
},
},
})
If redirectTo is omitted, shorthand fallbacks apply:
auth: 'user'falls back to/loginauth: 'guest'falls back to/
If you want global defaults for those fallbacks, use auth.redirects.
Default post-auth navigation:
auth.redirects.authenticatedis used whensignIn/signUpcomplete with an authenticated session and no explicitonSuccess.- If a preserved redirect query param is present and safe (
?redirect=), it takes precedence overauth.redirects.authenticated.
Server Configuration
Define your authentication logic in server/auth.config.ts, including plugins, providers, and settings.
defineServerAuth
Use the defineServerAuth helper to ensure type safety and access context. It accepts an object or function syntax.
import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
// Object syntax (simplest)
export default defineServerAuth({
emailAndPassword: { enabled: true }
})
// Function syntax (access context)
export default defineServerAuth((ctx) => ({
emailAndPassword: { enabled: true }
}))
secret and baseURL. You don't need to configure these in defineServerAuth.- Secret: Priority:
nuxt.config.tsruntimeConfig >NUXT_BETTER_AUTH_SECRET>BETTER_AUTH_SECRET - Base URL: The module auto-detects the base URL on Vercel/Cloudflare/Netlify. For other platforms, set
NUXT_PUBLIC_SITE_URL
Context Options
When using the function syntax, defineServerAuth callback receives a context object with useful properties:
import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
export default defineServerAuth((ctx) => ({
emailAndPassword: { enabled: true },
// Access the database connection via ctx.db when using NuxtHub
// Example: pass ctx.db to your own plugin/helper.
// Do not set `database` here when using module-managed adapters.
appName: ctx.runtimeConfig.public.siteUrl ? 'Better Auth App' : 'Better Auth',
// Access runtime config if needed
// someValue: ctx.runtimeConfig.customKey
}))
Session Enrichment
You can enrich session payloads with Better Auth's custom-session plugin through plugins in defineServerAuth. This module does not provide a separate requestSession.enrich option.
See the full recipe in Server Utilities.
Base URL Configuration
The module resolves siteUrl using this priority:
| Priority | Source | When Used |
|---|---|---|
| 1 | runtimeConfig.public.siteUrl | Explicit config (always wins) |
| 2 | Request URL | Auto-detected from the current Nitro request (event) |
| 3 | VERCEL_URL, CF_PAGES_URL, URL | Platform env vars (Vercel, Cloudflare, Netlify) |
| 4 | http://localhost:3000 | Development only |
In server handlers, pass event to serverAuth(event) so request URL detection can run. In non-request contexts (seed scripts, tasks, startup plugins), the module uses environment/platform fallbacks.
Set an explicit site URL in nuxt.config.ts for deterministic OAuth callbacks and origin checks:
export default defineNuxtConfig({
runtimeConfig: {
public: {
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'http://localhost:3000',
},
},
})
Use NUXT_PUBLIC_SITE_URL to provide this value per environment.
Custom domains or self-hosted: You should set runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) when using custom domains or deploying to your own VPS/server. Platform env vars return auto-generated URLs, not your custom domain.
NUXT_PUBLIC_SITE_URL="https://your-domain.com"
runtimeConfig.public.siteUrl (or NUXT_PUBLIC_SITE_URL) when callback consistency matters, such as local OAuth debugging, custom domains, or non-request contexts like seed scripts.Runtime Config
Configure secrets using environment variables (see Installation).
NUXT_BETTER_AUTH_SECRET="your-super-secret-key"
NUXT_PUBLIC_SITE_URL="https://your-domain.com" # Optional on Vercel/Cloudflare/Netlify
NUXT_BETTER_AUTH_SECRET as the primary secret variable. BETTER_AUTH_SECRET remains supported as a fallback for existing setups.For Module Authors
Other Nuxt modules can extend the authentication configuration:
// In your Nuxt module
export default defineNuxtModule({
setup(options, nuxt) {
nuxt.hook('better-auth:config:extend', (config) => {
config.plugins = [...(config.plugins || []), myPlugin()]
})
}
})
Access sessions from server handlers:
const { user, session } = await getUserSession(event)
if (!user) throw createError({ statusCode: 401 })