useAccAuth
Composable for all authentication actions and session state management.
Overview
useAccAuth() provides all authentication actions for your application. Each action communicates directly with the Accelerator auth endpoints at /acc/auth. After a successful action, the composable automatically syncs the global auth state so the rest of your app stays up to date.
Reactive access to the current auth state is available through three companion composables: useAccAuthSessions(), useAccAuthActiveSessionId(), and useAccAuthUser(). These return Nuxt useState refs that are kept in sync automatically.
Setup
Auth is disabled by default. Enable it in your nuxt.config.ts with enabled: true, a cookieSecret, and optionally a loginPage path for automatic redirects on 401/403 — see Auth error handling for how that works.
// nuxt.config.ts
export default defineNuxtConfig({
...,
levarneAcc: {
auth: {
enabled: true,
cookieSecret: process.env.COOKIE_SECRET, // required
loginPage: '/login', // optional — redirect on 401/403
},
}
})Usage
const {
signUp,
signInWithPassword,
verify,
signOut,
signOutAll,
switchSession,
refreshActiveSession,
syncAuthState,
getCurrentUser,
requestPasswordReset,
confirmPasswordReset,
changePassword,
setup2FA,
verify2FA,
signInWith2FA,
} = useAccAuth()State composables
Import these separately to read the current auth state reactively anywhere in your app. They are plain useState refs — read them in templates or watch them in composables.
const sessions = useAccAuthSessions() // Ref<AccSession[]>
const activeSessionId = useAccAuthActiveSessionId() // Ref<string | null>
const authUser = useAccAuthUser() // Ref<Record<string, unknown> | null>signUp
Registers a new user. The backend always sends an email — either a verification email for new/unconfirmed users, or a password reset email for existing confirmed users (to avoid revealing account existence). Supports optional reCAPTCHA — pass captchaAction and the $accApi plugin resolves the token automatically. See Email flows for details.
const result = await signUp({
username: 'user@example.com',
password: 'secret',
captchaAction: 'sign_up', // triggers automatic reCAPTCHA
baseUrl: 'https://your-origin.com', // optional — used to build links in emails
frontendPath: 'auth/confirm', // optional — path segment in verification/reset email links
})
// result: { success: boolean, errorCode?: AuthErrorCode }signInWithPassword
Authenticates a user with username and password. On success, syncs the auth state automatically. If the user is UNCONFIRMED, the backend sends a verification email and returns USER_NOT_CONFIRMED — see Email flows. If the user has 2FA enabled, the response includes errorCode: 'MFA_REQUIRED' and a challengeToken — use signInWith2FA to complete the login.
const result = await signInWithPassword({
username: 'user@example.com',
password: 'secret',
sessionDuration: 'long', // 'short' | 'long' — defaults to 'short'
baseUrl: 'https://your-origin.com', // optional
frontendPath: 'auth/confirm', // optional — used if user is UNCONFIRMED and a verification email is sent
})
// result: { success: boolean, sessionId?: string, errorCode?: AuthErrorCode }The session TTLs and access token lifetime can be overridden in your nuxt.config.ts. Access tokens are refreshed automatically by the $accApi proxy on every request when expired:
// nuxt.config.ts — override session and token TTLs
levarneAcc: {
auth: {
sessionTtlShortSeconds: 60 * 60, // default: 1 hour
sessionTtlLongSeconds: 60 * 60 * 24 * 30, // default: 30 days
accessTokenTtlSeconds: 60 * 15, // default: 15 minutes
},
}verify
Confirms a user's email using the token from a verification email. On success, creates a new session and syncs the auth state automatically. If the token is expired, the backend re-sends a fresh verification email and returns TOKEN_EXPIRED — see Email flows.
const result = await verify({
token: 'verification-token-from-email',
sessionDuration: 'long', // 'short' | 'long' — defaults to 'short'
baseUrl: 'https://your-origin.com', // optional — used if token is expired and a new email is sent
frontendPath: 'auth/confirm', // optional — path segment in the re-sent verification email link
})
// result: { success: boolean, sessionId?: string, errorCode?: AuthErrorCode }signOut / signOutAll
signOut() signs out the active session, or a specific session if sessionId is provided. signOutAll() terminates every session for the current user. Both sync the auth state on success.
// Sign out the active session
await signOut()
// Sign out a specific session by ID
await signOut({ sessionId: 'session_abc123' })
// Sign out all sessions for the current user
await signOutAll()switchSession
Switches the active session to a different one. Useful when a user has multiple sessions (e.g. multiple accounts). Syncs auth state on success.
// Switch to a different session (e.g. a second logged-in account)
const result = await switchSession('session_abc123')
// result: { success: boolean, activeSessionId?: string, errorCode?: AuthErrorCode }refreshActiveSession
Refreshes the active session's tokens. Call this proactively before a token expires to keep the session alive. Syncs auth state on success.
const result = await refreshActiveSession()
// result: { success: boolean, errorCode?: AuthErrorCode }syncAuthState
Fetches the current auth state from the server and updates the global state refs. Useful on app startup or after an external auth event.
// Fetch and apply the current auth state from the server
const authState = await syncAuthState()
// authState: { activeSessionId: string | null, sessions: AccSession[], activeUser: ... | null }getCurrentUser
Fetches the current user object from the server and updates useAccAuthUser(). Use this when you need a fresh copy of the user without doing a full state sync.
// Fetch just the user object and update useAccAuthUser()
const user = await getCurrentUser()Password reset
Two-step password reset flow. First call requestPasswordReset() to send the reset email. Then call confirmPasswordReset() with the token from that email. If the token is expired, confirmPasswordReset re-sends a fresh email automatically and returns TOKEN_EXPIRED. See Email flows for details.
// Step 1 — request a reset email
await requestPasswordReset({
username: 'user@example.com',
captchaAction: 'forgot_password', // triggers automatic reCAPTCHA
baseUrl: 'https://your-origin.com', // optional — used to build the reset link in the email
frontendPath: 'auth/reset-password', // optional — path segment in the reset email link
})
// Step 2 — confirm with the token from the email
await confirmPasswordReset({
token: 'reset-token-from-email',
newPassword: 'new-secret',
baseUrl: 'https://your-origin.com', // optional — used if token is expired and a new email is sent
frontendPath: 'auth/reset-password', // optional — used if token is expired and a new email is sent
})changePassword
Changes the password for the currently authenticated user. Requires the current password.
const result = await changePassword({
currentPassword: 'old-secret',
newPassword: 'new-secret',
})
// result: { success: boolean, errorCode?: AuthErrorCode }setup2FA
Generates a TOTP secret and otpauth:// URI for the authenticated user. Display the URI as a QR code so the user can scan it with their authenticator app, or show the secret for manual entry. Requires an active session.
const { secret, uri } = await setup2FA()
// secret: 'TO3Y45KKXTZR4RYQ' — 16-char base32 key for manual entry
// uri: 'otpauth://totp/user?secret=…&algorithm=SHA1&digits=6&period=30' — render as QR codeverify2FA
Confirms 2FA setup by submitting the 6-digit TOTP code from the user's authenticator app. Must be called after setup2FA. On success, syncs the auth state automatically.
const result = await verify2FA({
totp: '123456', // 6-digit code from the user's authenticator app
})
// result: { success: boolean, sessionId?: string, errorCode?: AuthErrorCode }signInWith2FA
Completes a 2FA login. When signInWithPassword returns MFA_REQUIRED with a challengeToken, call this function with the challenge token and the 6-digit TOTP code to authenticate. On success, syncs the auth state automatically.
// Step 1: normal sign in — returns MFA_REQUIRED when 2FA is enabled
const { success, errorCode, challengeToken } = await signInWithPassword({
username: 'user@example.com',
password: 'secret',
})
if (errorCode === 'MFA_REQUIRED' && challengeToken) {
// Step 2: complete login with TOTP code
const result = await signInWith2FA({
challengeToken,
totp: '123456', // 6-digit code from authenticator app
})
}Email flows
Several auth functions can trigger the backend to send an email. The frontendPath and baseUrl parameters control the link in that email. The final link format is {baseUrl}/{frontendPath}?token={tokenValue}.
frontendPath must be a relative path with no leading slash (e.g. auth/confirm). If omitted, the backend falls back to a hardcoded default (verify, resetpassword, etc. depending on the email type).
signUp
Always sends an email, but the type depends on user state:
- New user → sends a verification email.
- Existing
UNCONFIRMEDuser with expired token → re-sends the verification email.
signInWithPassword
Sends a verification email only when the user is UNCONFIRMED. Issues a new verification token, sends the email, then returns USER_NOT_CONFIRMED.
verify
Sends a fresh verification email only when the submitted token is expired. Re-issues a new token, sends the email, then returns TOKEN_EXPIRED.
requestPasswordReset
Sends a password reset email when the user exists, is CONFIRMED, and has no active reset token.
confirmPasswordReset
Sends a fresh password reset email only when the submitted token is expired or already used. Re-issues a new token, sends the email, then returns TOKEN_EXPIRED.
Return type
Most actions return a GenericAuthResult. Sign-in and sign-up have their own shapes.
Session storage
Sessions are stored server-side using a configurable storage driver. The driver is set via auth.storageDriver in your module config. The default is memory.
memory — the default. Stores sessions in the Nitro server process memory. No setup required, but sessions are lost on every server restart and not shared across multiple server instances. Only suitable for development or single-instance deployments where persistence is not needed.
// nuxt.config.ts — default, no extra config needed
levarneAcc: {
auth: {
enabled: true,
storageDriver: { type: 'memory' },
},
}fs-lite — not a built-in driver option, but Nitro's built-in devStorage supports it. In development you can mount a file-system storage under the acc-sessions key in your nuxt.config.ts. The module checks whether acc-sessions is already mounted before registering its own driver, so this takes precedence automatically. Sessions are written to .data/.acc-sessions and survive server restarts. This is the recommended setup for local development.
// nuxt.config.ts
// Use Nitro's devStorage to mount a file-system store under the acc-sessions key.
// The module skips registering its own driver when this mount already exists,
// so this takes precedence automatically. Sessions are written to .data/.acc-sessions.
export default defineNuxtConfig({
levarneAcc: {
auth: {
enabled: true,
cookieSecret: process.env.COOKIE_SECRET,
// no storageDriver needed — the devStorage mount below takes over
},
},
nitro: {
devStorage: {
'acc-sessions': {
driver: 'fs-lite',
base: '.data/.acc-sessions',
},
},
},
})dynamodb — persistent, scalable storage backed by an AWS DynamoDB table. Suitable for production. Sessions are wrapped with an in-process memory cache to reduce read latency. Requires the table to exist with pk (string) as the partition key. Set a TTL attribute named sessionTtl on the table to have DynamoDB expire sessions automatically.
// nuxt.config.ts
levarneAcc: {
auth: {
enabled: true,
cookieSecret: process.env.COOKIE_SECRET,
storageDriver: {
type: 'dynamodb',
region: 'eu-west-1',
table: 'sessions',
namespace: 'my-app',
endpoint: 'http://localhost:8000', // optional — for local DynamoDB
},
},
}postgresql — persistent storage backed by a PostgreSQL table. Suitable for production. The table is auto-created on first use. Sessions are wrapped with an in-process memory cache to reduce read latency. Requires the pg package (and @types/pg for TypeScript) in the consumer app. Expired rows are filtered out on read but not deleted automatically — schedule a periodic clean-up to remove them.
// nuxt.config.ts
levarneAcc: {
auth: {
enabled: true,
cookieSecret: process.env.COOKIE_SECRET,
storageDriver: {
type: 'postgresql',
url: process.env.DATABASE_URL,
namespace: 'my-app',
// tableName: 'acc_sessions', // optional — defaults to 'acc_sessions'
},
},
}