client.ts ```ts import { adminClient, multiSessionClient, twoFactorClient, usernameClient, } from 'better-auth/client/plugins'; import { createAuthClient } from 'better-auth/react'; import { env } from '@/env.mjs'; export const authClient = createAuthClient({ baseURL: env.NEXT_PUBLIC_APP_URL, plugins: [ usernameClient(), adminClient(), multiSessionClient(), twoFactorClient(), ], }); export const { signIn, signOut, signUp, useSession } = authClient; ``` ```ts import { PrismaClient } from '@prisma/client'; import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import { nextCookies } from 'better-auth/next-js'; import { admin, multiSession, twoFactor, username } from 'better-auth/plugins'; import { UserRole } from '@/lib/enums'; import { sendPasswordResetEmail } from '@/lib/next-auth/mail'; import { env } from '@/env.mjs'; const prisma = new PrismaClient(); export const auth = betterAuth({ appName: 'Valuemetrix', database: prismaAdapter(prisma, { provider: 'mongodb', }), user: { modelName: 'User', }, logger: { disabled: process.env.NODE_ENV === 'production', level: 'debug', }, account: { fields: { accountId: 'providerAccountId', refreshToken: 'refreshToken', accessToken: 'accessToken', idToken: 'idToken', accessTokenExpiresAt: 'access_token_expires', }, accountLinking: { enabled: true, trustedProviders: ['google'], }, }, emailAndPassword: { enabled: true, async sendResetPassword(data) { await sendPasswordResetEmail(data.user.email, data.token); }, }, socialProviders: { google: { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, redirectUri: env.NEXT_PUBLIC_APP_URL + '/api/auth/callback/google', enabled: true, }, }, plugins: [ nextCookies(), admin({ defaultRole: UserRole.USER, adminRole: UserRole.ADMIN, }), multiSession(), username(), twoFactor(), ], trustedOrigins: ['localhost:3000'], }); ``` ```prisma // prisma/schema.prisma datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } enum UserRole { ADMIN USER } model User { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) updatedAt DateTime @updatedAt name String @default("") email String @unique emailVerified DateTime? image String? @default("") bio String? @default("") password String? role UserRole @default(USER) twoFactorEnabled Boolean? @default(false) accounts Account[] sessions Session[] banned Boolean? banReason String? banExpires DateTime? username String? twofactors TwoFactor[] twoFactorConfirmation TwoFactorConfirmation? @@unique([username]) } model Account { id String @id @default(auto()) @map("_id") @db.ObjectId password String? createdAt DateTime updatedAt DateTime provider String expires_at Int? scope String? type String token_type String? session_state String? userId String @db.ObjectId user User @relation(fields: [userId], references: [id], onDelete: Cascade) providerId String accessTokenExpiresAt DateTime? refreshTokenExpiresAt DateTime? accountId String @map("providerAccountId") accessToken String? @map("access_token") refreshToken String? @map("refresh_token") idToken String? @map("id_token") @@unique([provider, accountId]) @@map("account") } model Session { id String @id @map("_id") expiresAt DateTime token String createdAt DateTime updatedAt DateTime ipAddress String? userAgent String? userId String @db.ObjectId user User @relation(fields: [userId], references: [id], onDelete: Cascade) impersonatedBy String? @@unique([token]) @@map("session") } model Verification { id String @id @map("_id") identifier String value String expiresAt DateTime createdAt DateTime? updatedAt DateTime? @@map("verification") } model TwoFactor { id String @id @map("_id") secret String backupCodes String userId String @db.ObjectId user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@map("twoFactor") } ```