Better Auth Integration
DBS uses Better Auth as its authentication backbone. Better Auth is a framework-agnostic, TypeScript-first library that handles sessions, email/password login, two-factor authentication (2FA via TOTP), Passkeys (WebAuthn), and OAuth providers — all with a type-safe API.
Key Files
| File | Purpose |
|---|---|
src/lib/auth.ts | Server-side Better Auth configuration. Defines plugins, database adapter, and session options. |
src/lib/auth-client.ts | Client-side Better Auth instance. Used in React components and hooks. |
src/app/api/auth/[...all]/route.ts | Next.js route handler that delegates all auth requests to Better Auth. |
Server Configuration (auth.ts)
// src/lib/auth.ts
import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';
import { twoFactor, passkey } from 'better-auth/plugins';
import { prisma } from '@/lib/prisma';
export const auth = betterAuth({
database: prismaAdapter(prisma, { provider: 'postgresql' }),
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
},
plugins: [
twoFactor(), // TOTP-based 2FA
passkey(), // WebAuthn / Passkeys
],
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24, // Refresh session every 24h
cookieCache: {
enabled: true,
maxAge: 5 * 60, // Cache for 5 minutes
},
},
});Client Configuration (auth-client.ts)
// src/lib/auth-client.ts
import { createAuthClient } from 'better-auth/react';
import { twoFactorClient, passkeyClient } from 'better-auth/client/plugins';
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_APP_URL,
plugins: [
twoFactorClient(),
passkeyClient(),
],
});
// Named exports for convenience
export const {
signIn,
signOut,
signUp,
useSession,
getSession,
} = authClient;Route Handler
// src/app/api/auth/[...all]/route.ts
import { auth } from '@/lib/auth';
import { toNextJsHandler } from 'better-auth/next-js';
export const { GET, POST } = toNextJsHandler(auth);This single file handles all Better Auth endpoints: login, logout, register, session refresh, 2FA setup, etc.
Available Auth Features
Email & Password
Standard email/password authentication with email verification enforced. Registration triggers a verification email via Resend before the account becomes active.
import { authClient } from '@/lib/auth-client';
// Sign up
await authClient.signUp.email({
email: 'user@example.com',
password: 'SecurePass123!',
name: 'Jane Doe',
});
// Sign in
await authClient.signIn.email({
email: 'user@example.com',
password: 'SecurePass123!',
});Reading the Session on the Server
Use auth.api.getSession() in Server Components and API routes:
import { auth } from '@/lib/auth';
import { headers } from 'next/headers';
export default async function ServerPage() {
const session = await auth.api.getSession({
headers: await headers(),
});
if (!session) {
redirect('/login');
}
return <div>Hello, {session.user.name}</div>;
}In API routes, use apiGuard() instead of calling auth.api.getSession() directly. apiGuard automatically handles the 401 response, rate limiting, and permission checking.
Reading the Session on the Client
'use client';
import { useSession } from '@/lib/auth-client';
export function UserAvatar() {
const { data: session, isPending } = useSession();
if (isPending) return <Skeleton />;
if (!session) return null;
return <Avatar src={session.user.image} name={session.user.name} />;
}Email Verification Flow
User Registers
authClient.signUp.email() is called. Better Auth creates the user with emailVerified: false.
Verification Email Sent
The sendVerificationEmail callback in auth.ts fires, calling sendVerificationEmail() from src/lib/email.ts via Resend.
User Clicks Link
The link routes to /api/auth/verify-email?token=... which Better Auth handles automatically.
Account Activated
emailVerified is set to true in the database. The user can now log in.
Users who have not verified their email will receive a 403 if they attempt to access any dashboard route. This is enforced by the Better Auth session plugin configuration.