Authentication Configuration
Configure authentication methods, OAuth providers, email verification, and customize behavior for your application.
Vibestacks authentication is highly configurable. Enable or disable sign-in methods, configure OAuth providers, and customize behavior through configuration files.
Configuration File
Authentication settings are defined in the auth configuration:
export const auth = betterAuth({
// Database connection
database: drizzleAdapter(db, {
provider: "pg",
schema,
}),
// Email/password authentication
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
},
// Social providers
socialProviders: {
google: {
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
},
// Add more providers here
},
// Plugins
plugins: [
magicLink({
sendMagicLink: async ({ email, url }) => {
// Email sending logic
},
}),
// stripe(), twoFactor(), etc.
],
})Authentication Methods
Email & Password
Enable or disable traditional email/password authentication:
emailAndPassword: {
enabled: true, // Set to false to disable
requireEmailVerification: true, // Require email confirmation
}Email Verification
When requireEmailVerification is true, users cannot sign in until they click the verification link sent to their email.
Magic Link
Passwordless authentication via email:
plugins: [
magicLink({
sendMagicLink: async ({ email, url }) => {
await resend.emails.send({
from: "noreply@yourdomain.com",
to: email,
subject: "Sign in to Your App",
react: MagicLinkEmail({ url }),
})
},
}),
]To disable magic links, remove the plugin from the configuration.
Two-Factor Authentication
TOTP-based 2FA (optional):
plugins: [
twoFactor({
issuer: "Your App Name", // Shows in authenticator apps
}),
]When enabled, users can set up 2FA in their account settings.
OAuth Providers
Google OAuth
-
Create credentials at Google Cloud Console
-
Configure redirect URI:
https://yourdomain.com/api/auth/callback/googleFor local development:
http://localhost:3000/api/auth/callback/google -
Add environment variables:
.env.local GOOGLE_CLIENT_ID=your_client_id GOOGLE_CLIENT_SECRET=your_client_secret -
Enable in configuration:
socialProviders: { google: { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, }, }
GitHub OAuth
-
Create OAuth app at GitHub Developer Settings
-
Configure callback URL:
https://yourdomain.com/api/auth/callback/github -
Add environment variables:
.env.local GITHUB_CLIENT_ID=your_client_id GITHUB_CLIENT_SECRET=your_client_secret -
Enable in configuration:
socialProviders: { github: { clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET, }, }
Environment Variables
| Variable | Required | Description |
|---|---|---|
BETTER_AUTH_SECRET | Yes | Secret for signing session cookies |
DATABASE_URL | Yes | PostgreSQL connection string |
NEXT_PUBLIC_SITE_URL | Yes | Public site URL for email links |
RESEND_API_KEY | Yes* | Email delivery (*if email features enabled) |
GOOGLE_CLIENT_ID | No | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | No | Google OAuth client secret |
GITHUB_CLIENT_ID | No | GitHub OAuth client ID |
GITHUB_CLIENT_SECRET | No | GitHub OAuth client secret |
Generate a secure BETTER_AUTH_SECRET:
openssl rand -base64 32Keep Secrets Safe
Never commit OAuth secrets or BETTER_AUTH_SECRET to version control. Use environment variables in production.
URL Configuration
Customize authentication page paths:
const authConfig = {
urls: {
signIn: "/sign-in",
signUp: "/sign-up",
forgotPassword: "/forgot-password",
resetPassword: "/reset-password",
callback: "/dashboard", // Post-auth redirect
},
}Email Templates
Authentication emails are React components in the emails/ directory:
emails/
├── magic-link.tsx # Magic link sign-in
├── verify-email.tsx # Email verification
└── reset-password.tsx # Password resetCustomize the templates to match your brand. See Email System for details.
Stripe Integration
Better Auth integrates with Stripe to automatically create customers:
plugins: [
stripe({
stripeClient,
stripeWebhookSecret: env.STRIPE_WEBHOOK_SECRET,
createCustomerOnSignUp: true, // Auto-create Stripe customer
}),
]When enabled:
- New users automatically get a Stripe customer ID
- Customer ID stored in
users.stripeCustomerId - Enables seamless checkout and subscription management
See Payments System for details.
Protected Routes
Server Components
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
import { redirect } from "next/navigation"
export default async function DashboardPage() {
const session = await auth.api.getSession({
headers: await headers(),
})
if (!session) {
redirect("/sign-in")
}
return <Dashboard user={session.user} />
}Client Components
"use client"
import { useSession } from "@/lib/auth-client"
import { useRouter } from "next/navigation"
import { useEffect } from "react"
export function ProtectedComponent() {
const { data: session, isPending } = useSession()
const router = useRouter()
useEffect(() => {
if (!isPending && !session) {
router.push("/sign-in")
}
}, [session, isPending, router])
if (isPending) return <Loading />
if (!session) return null
return <Content user={session.user} />
}Middleware (Optional)
For route-level protection:
import { auth } from "@/lib/auth"
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export async function middleware(request: NextRequest) {
const session = await auth.api.getSession({
headers: request.headers,
})
if (!session && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/sign-in", request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ["/dashboard/:path*"],
}Common Configurations
Simple email/password authentication:
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg", schema }),
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
},
})Social sign-in only (no passwords):
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg", schema }),
emailAndPassword: {
enabled: false,
},
socialProviders: {
google: {
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
},
},
})All authentication methods enabled:
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg", schema }),
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
},
socialProviders: {
google: { /* ... */ },
github: { /* ... */ },
},
plugins: [
magicLink({ /* ... */ }),
twoFactor({ issuer: "Your App" }),
stripe({ /* ... */ }),
],
})Next Steps
- Authentication Flows - Understand the complete user journey
- Email System - Customize email templates
- Payments System - Stripe integration details