Demo
General

Authentication

Learn how to manage user authentication and authorization with Better Auth.

The Pro Next.js Drizzle starter kit uses Better Auth for robust and flexible authentication. It supports various providers, multi-factor authentication and organization-based access control.

Setup

Authentication is primarily configured in lib/auth/index.ts. Follow the Setup to set up the basic environment variables.

lib/auth/index.ts
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';

import { db } from '@/lib/db';
import { env } from '@/lib/env';

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'pg'
  }),
  emailAndPassword: {
    enabled: true
  },
  socialProviders: {
    google: {
      clientId: env.GOOGLE_CLIENT_ID,
      clientSecret: env.GOOGLE_CLIENT_SECRET
    }
  }
  // ... other configurations
});

Client Usage

On the client side, use the authClient and the useSession hook to access user information.

hooks/use-session.tsx
import { authClient } from '@/lib/auth/client';

const { data: session, isPending } = authClient.useSession();

Protecting Routes

API Routes

Better Auth handles authentication through API routes at app/api/auth/[...all]/route.ts. This route proxies all authentication requests to Better Auth.

Page Protection

Routes are protected by checking the session in Server Components. Use getSession() from @/lib/auth/server to verify authentication.

Server-side (tRPC)

For API routes, use protectedProcedure or protectedOrganizationProcedure in your tRPC routers.

trpc/routers/organization/organization-router.ts
import { createTRPCRouter, protectedOrganizationProcedure } from '@/trpc/init';

export const organizationRouter = createTRPCRouter({
  get: protectedOrganizationProcedure.query(async ({ ctx }) => {
    // Current organization is available in ctx.organization
    return ctx.organization;
  })
});

Organizations

Multi-tenancy is built-in. Users can create, join and switch between organizations.

Creating an Organization

components/organization-switcher.tsx
await authClient.organization.create({
  name: 'My New Company'
});

Inviting Members

lib/actions/organization.ts
await authClient.organization.inviteMember({
  email: 'teammate@example.com',
  role: 'member'
});

Admin Features

Platform admins can manage users and organizations through a dedicated admin panel.

Impersonation

Admins can impersonate users for debugging purposes.

lib/actions/admin.ts
await authClient.admin.impersonateUser({
  userId: 'user-id-to-impersonate'
});

Banning Users

Admins can ban users permanently or for a specific duration.

trpc/routers/admin/admin-user-router.ts
import { banUserAdminSchema } from '@/schemas/admin-user-schemas';
import { createTRPCRouter, protectedAdminProcedure } from '@/trpc/init';

export const adminUserRouter = createTRPCRouter({
  banUser: protectedAdminProcedure
    .input(banUserAdminSchema)
    .mutation(async ({ input, ctx }) => {
      // Ban user logic
      return { success: true };
    })
});