@xenterprises/nuxt-x-auth-better
v0.3.2
Published
BetterAuth authentication layer for Nuxt
Readme
@xenterprises/nuxt-x-auth-better
BetterAuth authentication layer for Nuxt 4. Pre-built UI components, route protection, OAuth, magic link, and password reset flows — all configurable via app.config.ts.
Install
npm install @xenterprises/nuxt-x-auth-better better-authSetup
1. Extend the layer
// nuxt.config.ts
export default defineNuxtConfig({
extends: ['@xenterprises/nuxt-x-auth-better'],
})2. Configure
// app.config.ts
export default defineAppConfig({
xAuth: {
features: {
oauth: true,
magicLink: true,
forgotPassword: true,
signup: true,
},
redirects: {
afterLogin: '/dashboard',
afterSignup: '/dashboard',
},
oauthProviders: [
{ id: 'google', label: 'Google', icon: 'i-simple-icons-google' },
{ id: 'github', label: 'GitHub', icon: 'i-simple-icons-github' },
],
ui: {
showLogo: true,
logoUrl: '/logo.svg',
brandName: 'My App',
},
},
})3. Set environment variables
NUXT_PUBLIC_X_AUTH_BASE_URL=https://api.example.comUsage
<script setup>
const {
user,
isAuthenticated,
isLoading,
login,
signup,
logout,
loginWithProvider,
sendMagicLink,
forgotPassword,
resetPassword,
changePassword,
updateUser,
deleteAccount,
getToken,
getAuthHeaders,
} = useXAuth()
await login('[email protected]', 'password')
await loginWithProvider('google')
await sendMagicLink('[email protected]')
await signup('[email protected]', 'password', 'John Doe')
await forgotPassword('[email protected]')
await changePassword('oldpass', 'newpass')
await updateUser({ name: 'New Name' })
await logout()
</script>Options (app.config.ts)
xAuth.tokens
| Name | Type | Default | Description |
|------|------|---------|-------------|
| accessCookie | string | "x_auth_access" | Cookie name for access token |
| refreshCookie | string | "x_auth_refresh" | Cookie name for refresh token |
| hasRefresh | boolean | true | Enable refresh token storage |
xAuth.redirects
| Name | Type | Default | Description |
|------|------|---------|-------------|
| login | string | "/auth/login" | Login page path |
| signup | string | "/auth/signup" | Signup page path |
| afterLogin | string | "/" | Redirect after successful login |
| afterSignup | string | "/" | Redirect after successful signup |
| afterLogout | string | "/auth/login" | Redirect after logout |
| forgotPassword | string | "/auth/forgot-password" | Forgot password page path |
xAuth.features
| Name | Type | Default | Description |
|------|------|---------|-------------|
| oauth | boolean | false | Enable OAuth provider buttons |
| magicLink | boolean | false | Enable magic link authentication |
| otp | boolean | false | Enable OTP authentication |
| forgotPassword | boolean | true | Enable forgot password flow |
| signup | boolean | true | Enable signup form and link |
xAuth.oauthProviders
Array of { id, label, icon } objects. Supported provider IDs: google, github, microsoft, facebook, twitter, apple, linkedin, discord, spotify.
xAuth.ui
| Name | Type | Default | Description |
|------|------|---------|-------------|
| showLogo | boolean | true | Show logo in auth layout |
| showBrandName | boolean | true | Show brand name below logo |
| logoUrl | string | "" | URL to logo image |
| brandName | string | "" | Brand name text |
| tagline | string | "" | Tagline below brand name |
| layout | "centered" \| "split" | "centered" | Auth page layout style |
| background.enabled | boolean | true | Enable background image |
| background.imageUrl | string | "" | Custom background image URL (random default if empty) |
| background.overlayOpacity | number | 55 | Overlay opacity (0-100) |
| background.blur | boolean | true | Blur background image |
| card.glass | boolean | false | Glass morphism effect on card |
| card.logoUrl | string | "" | Logo shown inside the auth card |
| form.showSeparator | boolean | true | Show "or" separator between OAuth and form |
| legal.copyright | string | "" | Footer copyright text |
| legal.links | Array<{label, to}> | [] | Footer legal links |
Composable: useXAuth()
Reactive State
| Property | Type | Description |
|----------|------|-------------|
| user | Ref<AuthUser \| null> | Current authenticated user |
| isAuthenticated | Ref<boolean> | Whether user is authenticated |
| isLoading | Ref<boolean> | Whether session is loading |
| emailSent | Ref<boolean> | Whether magic link / reset email was sent |
| codeSent | Ref<boolean> | Whether OTP code was sent |
| session | Ref<SessionData> | Raw Better Auth session data |
| sessionError | Ref<Error> | Session error if any |
| config | Ref<AuthConfig> | Current auth configuration |
Methods
| Method | Returns | Description |
|--------|---------|-------------|
| login(email, password) | AuthUser \| null | Email/password sign in |
| signup(email, password, name?) | AuthUser \| null | Create account |
| logout() | boolean | Sign out and redirect |
| loginWithProvider(provider) | boolean | Start OAuth flow |
| sendMagicLink(email, options?) | boolean | Send magic link email |
| forgotPassword(email) | boolean | Send password reset email |
| resetPassword(token, newPassword) | true \| { error } | Reset password with token |
| changePassword(current, new) | true \| { error } | Change password (authenticated) |
| updateUser({ name?, image? }) | true \| { error } | Update user profile |
| deleteAccount() | boolean | Permanently delete account |
| getCurrentUser() | AuthUser \| null | Get current user (fetches if needed) |
| getToken() | string \| null | Get access token |
| getAuthHeaders() | Record<string, string> | Get { Authorization: 'Bearer ...' } |
| handleMagicLinkCallback(token) | true \| { error } | Verify magic link token |
| resetState() | void | Reset emailSent / codeSent flags |
AuthUser Type
interface AuthUser {
id: string
email: string
name: string
avatar?: string
emailVerified: boolean
metadata?: Record<string, any>
}Components
| Component | Description |
|-----------|-------------|
| XAuthLogin | Email/password login form with OAuth, magic link, and forgot password links |
| XAuthSignup | Registration form with terms/privacy links |
| XAuthForgotPassword | Password reset request form with success state |
| XAuthMagicLink | Magic link email form with success state |
| XAuthOAuthButton | Single OAuth provider button with brand icon |
| XAuthOAuthButtonGroup | All configured OAuth provider buttons |
| XAuthHandler | Callback handler for OAuth, magic link, password reset, email verification |
Pages (auto-registered)
| Path | Description | Route Type |
|------|-------------|------------|
| /auth/login | Login page | Guest-only |
| /auth/signup | Registration page | Guest-only |
| /auth/forgot-password | Password reset request | Guest-only |
| /auth/magic-link | Magic link authentication | Guest-only |
| /auth/reset-password | Set new password (with token) | Guest-only |
| /auth/logout | Logout handler | Public |
| /auth/handler/* | OAuth / magic link / password reset callbacks | Public |
All other routes are protected (require authentication).
Environment Variables
| Name | Required | Description |
|------|----------|-------------|
| NUXT_PUBLIC_X_AUTH_BASE_URL | Yes | Base URL of your Better Auth backend (e.g. https://api.example.com) |
The auth path is configurable via runtimeConfig.public.x.auth.authPath (default: /auth).
Error Reference
All errors are displayed as toast notifications. Methods return null, false, or { error: string } on failure.
| Context | Error | When |
|---------|-------|------|
| Login | "Please enter both email and password." | Empty email or password |
| Login | "Invalid credentials." | Wrong email/password (from API) |
| Signup | "Please enter both email and password." | Empty email or password |
| Signup | "Could not create account." | API error (e.g. email exists) |
| Forgot Password | "Please enter your email address." | Empty email |
| Reset Password | "Token and new password are required" | Missing token or password |
| Change Password | "Please enter both current and new passwords." | Empty input |
| Magic Link | "Please enter your email address." | Empty email |
| OAuth | "{provider} Login Failed" | OAuth flow error |
| Logout | "Failed to sign out." | API error |
| Update Profile | "Could not update profile." | API error |
| Delete Account | "Could not delete account." | API error |
How It Works
This layer uses Better Auth's official Vue client (better-auth/vue) via createAuthClient. The client communicates with your Better Auth backend using cookie-based sessions (credentials: 'include').
Session management:
createAuthClientis instantiated once (singleton) and provides a reactiveuseSession()ref that auto-updates. The composable wraps this with convenience methods.Route protection: A global middleware (
auth.global.ts) runs on every navigation. It classifies routes as public, guest-only, or protected, then callsgetCurrentUser()to check auth state.Auth layout: All
/auth/*pages use theauthlayout which provides a card-style UI with background image, branding, and animations.OAuth flow:
loginWithProvider()calls Better Auth'ssignIn.social()which redirects to the provider. The callback lands on/auth/handler/oauth-callbackwhere the Handler component refreshes the session.Token access:
getToken()andgetAuthHeaders()extract the access token from the Better Auth session for use with your own API calls.
Layer Architecture
nuxt.config.ts: Registers@nuxt/uimodule, loads the auth CSS, and definesruntimeConfig.public.x.authfor base URL and auth path.app/app.config.ts: Defines all configurable options (tokens, redirects, features, OAuth providers, UI settings) with defaults. Consumer apps override these in their ownapp.config.ts.app/composables/useXAuth.ts: Core composable wrapping Better Auth's Vue client with typed methods for all auth flows.app/middleware/auth.global.ts: Global route middleware for auth-based route protection.app/plugins/auth-token.ts: Provides$getAuthTokenfor use in other plugins/composables.app/layouts/auth.vue: Visual auth layout with card design, background image, and branding.app/components/XAuth/*: Pre-built form components using Nuxt UI'sUAuthForm.app/pages/auth/*: Auto-registered auth pages.app/utils/: Cookie storage helper and field normalization utilities.
Testing
npm run test # Watch mode
npm run test:run # Single runRequirements
- Nuxt 4+
- Better Auth 1.0+
- @nuxt/ui v4+ (included as dependency)
License
UNLICENSED
