Quick Start
Add authentication to your Next.js app in 10 minutes using Better Auth.
This guide shows you how to add authentication to a Next.js application using Better Auth with Transactional Auth as your identity provider.
Prerequisites
- A Transactional account (sign up free)
- A Next.js 14+ application
- PostgreSQL database (for session storage)
Step 1: Create a Transactional Auth Application
- Go to your Transactional Dashboard
- Navigate to Auth > Applications
- Click Create Application
- Configure:
- Name: Your app name
- Type: Server
- Redirect URIs:
https://yourapp.com/api/auth/callback/transactional - Allowed Origins:
https://yourapp.com
- Copy your Client ID and Client Secret
Note: For local development, also add
http://localhost:3000/api/auth/callback/transactionalandhttp://localhost:3000.
Step 2: Install Better Auth
npm install better-authStep 3: Configure Environment Variables
Create .env.local:
# Your app URL
BETTER_AUTH_URL=http://localhost:3000
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Transactional Auth (use your app's Auth Domain from the dashboard)
TRANSACTIONAL_AUTH_URL=https://your-app-name-abc123.auth.usetransactional.com
TRANSACTIONAL_CLIENT_ID=your_client_id
TRANSACTIONAL_CLIENT_SECRET=your_client_secret
# Database for Better Auth sessions
DATABASE_URL=postgresql://user:password@localhost:5432/myappStep 4: Create Auth Configuration
Create lib/auth.ts:
import { betterAuth } from "better-auth";
import { genericOAuth } from "better-auth/plugins";
export const auth = betterAuth({
baseURL: process.env.BETTER_AUTH_URL!,
database: {
provider: "postgresql",
url: process.env.DATABASE_URL!,
},
plugins: [
genericOAuth({
config: [
{
providerId: "transactional",
clientId: process.env.TRANSACTIONAL_CLIENT_ID!,
clientSecret: process.env.TRANSACTIONAL_CLIENT_SECRET!,
authorizationUrl: `${process.env.TRANSACTIONAL_AUTH_URL}/auth`,
tokenUrl: `${process.env.TRANSACTIONAL_AUTH_URL}/token`,
userInfoUrl: `${process.env.TRANSACTIONAL_AUTH_URL}/me`,
scopes: ["openid", "profile", "email"],
pkce: true,
},
],
}),
],
});Step 5: Create API Route
Create app/api/auth/[...all]/route.ts:
import { auth } from "@/lib/auth";
import { toNextJsHandler } from "better-auth/next-js";
export const { GET, POST } = toNextJsHandler(auth.handler);Step 6: Create Auth Client
Create lib/auth-client.ts:
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_APP_URL,
});
export const { signIn, signOut, useSession } = authClient;Step 7: Run Database Migration
Create the required tables:
npx better-auth migrateStep 8: Add Login Button
Create components/auth-buttons.tsx:
"use client";
import { signIn, signOut, useSession } from "@/lib/auth-client";
export function LoginButton() {
return (
<button
onClick={() => signIn.social({
provider: "transactional",
callbackURL: "/dashboard"
})}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Sign in
</button>
);
}
export function LogoutButton() {
return (
<button
onClick={() => signOut({ callbackURL: "/" })}
className="px-4 py-2 bg-gray-200 rounded-lg hover:bg-gray-300"
>
Sign out
</button>
);
}
export function AuthStatus() {
const { data: session, isPending } = useSession();
if (isPending) return <div>Loading...</div>;
if (session) {
return (
<div className="flex items-center gap-4">
<span>Welcome, {session.user.name || session.user.email}</span>
<LogoutButton />
</div>
);
}
return <LoginButton />;
}Step 9: Protect Pages
Client Component (with hook)
"use client";
import { useSession } from "@/lib/auth-client";
import { redirect } from "next/navigation";
export default function DashboardPage() {
const { data: session, isPending } = useSession();
if (isPending) return <div>Loading...</div>;
if (!session) redirect("/login");
return (
<div>
<h1>Dashboard</h1>
<p>Email: {session.user.email}</p>
<p>Name: {session.user.name}</p>
</div>
);
}Server Component
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("/login");
return (
<div>
<h1>Dashboard</h1>
<p>Email: {session.user.email}</p>
</div>
);
}Step 10: Create Login Page
Create app/login/page.tsx:
import { LoginButton } from "@/components/auth-buttons";
export default function LoginPage() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h1 className="text-2xl font-bold mb-8">Welcome</h1>
<LoginButton />
</div>
</div>
);
}Test Your Integration
- Start your app:
npm run dev - Visit
http://localhost:3000/login - Click "Sign in" - you'll be redirected to Transactional Auth
- Create an account or sign in
- After authentication, you'll be redirected to
/dashboard
Production Deployment
Update your environment variables for production:
BETTER_AUTH_URL=https://yourapp.com
NEXT_PUBLIC_APP_URL=https://yourapp.com
TRANSACTIONAL_AUTH_URL=https://auth.usetransactional.com
DATABASE_URL=postgresql://user:password@prod-host:5432/myappAnd update your Transactional Auth application with production URLs.
What's Stored Where?
| Data | Location | Managed By |
|---|---|---|
| User accounts | Transactional Auth | Transactional |
| Passwords | Transactional Auth | Transactional |
| MFA settings | Transactional Auth | Transactional |
| Sessions | Your database | Better Auth |
| OAuth tokens | Your database | Better Auth |
Next Steps
- Better Auth Integration - Advanced configuration and features
- MFA - Enable multi-factor authentication
- Organizations - Add B2B multi-tenancy
- SSO - Enterprise single sign-on
On This Page
- Prerequisites
- Step 1: Create a Transactional Auth Application
- Step 2: Install Better Auth
- Step 3: Configure Environment Variables
- Step 4: Create Auth Configuration
- Step 5: Create API Route
- Step 6: Create Auth Client
- Step 7: Run Database Migration
- Step 8: Add Login Button
- Step 9: Protect Pages
- Client Component (with hook)
- Server Component
- Step 10: Create Login Page
- Test Your Integration
- Production Deployment
- What's Stored Where?
- Next Steps