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 },
appName: ctx.runtimeConfig.public.siteUrl ? 'Better Auth App' : 'Better Auth',
}))
ctx.runtimeConfig: Nuxt runtime config.ctx.db: NuxtHub database connection when NuxtHub DB is enabled. Do not setdatabasewhen using module-managed adapters.ctx.requestOrigin: Current request origin when auth is created withserverAuth(event).
Use requestOrigin when Better Auth config needs the current request host, such as trusted origins:
import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
export default defineServerAuth(({ requestOrigin }) => ({
trustedOrigins: requestOrigin ? [requestOrigin] : [],
}))
runtimeConfig.public.siteUrl. requestOrigin is optional and only available when auth is created from a request event. If allowed origins vary while using an explicit siteUrl, configure those origins explicitly or use Better Auth's trustedOrigins function form, because the auth instance can be cached.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 })