Why Better Auth?
Type-Safe
Full TypeScript support with automatic type inference
Framework Agnostic
Works with any framework, but optimized for Next.js
Database-First
Uses your existing database (PostgreSQL via Drizzle)
Flexible
Easy to customize and extend
Configuration
Team Auth (lib/auth.ts)
Client Portal Auth (lib/client-auth.ts)
API Handler
Better Auth provides a catch-all API handler:/api/auth/sign-in/google/api/auth/sign-out/api/auth/session/api/auth/callback/google
Client-Side Hooks
Team Auth Client (lib/auth-client.ts)
Features
Google OAuth Integration
Configuration:- Create OAuth credentials in Google Cloud Console
- Set authorized redirect URIs:
http://localhost:3000/api/auth/callback/google(local)https://charle.agency/api/auth/callback/google(production)
- Add credentials to
.env.local
- User clicks “Sign in with Google”
- Redirected to Google consent screen
- Google redirects back to
/api/auth/callback/google - Better Auth creates session
- User redirected to dashboard
- Google profile picture is downloaded
- Uploaded to Cloudflare R2
- Stored in
user.imagefield - Updated on every sign-in
Invite-Only System
- Admin creates user account via admin panel (status: “pending”)
- Admin sends invitation email (status: “sent”)
- User clicks “Sign in with Google”
- Better Auth verifies email exists in database
- If not found → “No account found” error
- If found → Session created, status auto-updated to “active”
Session Management
Server-Side:Database Hooks
Better Auth allows you to hook into lifecycle events:pending→ Account created but no invite sentsent→ Invite email sent, awaiting first loginactive→ User has logged in (auto-activated on first login after invite)
Security
CSRF Protection
Better Auth includes built-in CSRF protection:- All POST requests require valid CSRF token
- Tokens are stored in cookies
- Automatically validated on each request
Session Security
- Sessions stored server-side in PostgreSQL
- Random, unpredictable session tokens
- Automatic expiry after 7 days
- IP address and user agent tracked
Password Security (Client Portal)
- Passwords hashed with bcrypt (cost factor 10)
- Never stored in plain text
- Password reset requires email verification
Customization
Adding Custom Fields
Custom Session Data
Environment Variables
Troubleshooting
”No account found” Error
Cause: User trying to sign in with Google but email doesn’t exist in database. Fix: Admin must create user account first via admin panel.CORS Errors
Cause:BETTER_AUTH_URL doesn’t match actual URL.
Fix: Verify .env.local has correct URL for environment:
- Local:
http://localhost:3000 - Production:
https://charle.agency
Session Not Persisting
Cause: Cookies not being set (usually HTTPS/domain issues). Fix:- Check
BETTER_AUTH_URLmatches your actual domain - Ensure HTTPS in production
- Clear cookies and try again
Related Documentation
Authentication Overview
Auth architecture and systems
Permissions
Role-based access control
Sessions
Session lifecycle management
Better Auth Docs
Official Better Auth documentation