Authentication
ZeroDrag uses NextAuth.js v4 with two authentication methods: Google OAuth and passwordless magic links.
What This System Does
The authentication system handles:
- User sign-in with Google OAuth (one-click authentication)
- Passwordless email authentication via magic links
- Automatic account linking based on email address
- Session management with JWT tokens
- Protected route enforcement
- Server and client-side session access
Why It Exists
Authentication is the foundation for all user-specific features. It ensures users can securely access their accounts, subscriptions, and entitlements. The dual-provider approach (OAuth + magic links) balances convenience with accessibility.
When You Need to Care About It
You'll interact with authentication when:
- Protecting pages or API routes that require user authentication
- Checking user entitlements for feature gating
- Customizing the sign-in UI or flow
- Adding additional OAuth providers (beyond Google)
- Modifying session duration or token settings
Key Concepts
Sessions
Sessions are JWT-based tokens stored in HTTP-only cookies. They last 30 days and automatically refresh every 24 hours when the user is active.
Account Linking
If a user signs up with a magic link and later uses Google OAuth (or vice versa) with the same email, the accounts are automatically linked. This prevents duplicate accounts.
Protected Routes
Pages inside /app/(protected)/ automatically require authentication. The layout calls requireAuth() and redirects unauthenticated users to /auth.
Server vs Client Sessions
Server-side code uses getServerSession() or helper functions like requireAuth(). Client-side code uses the useSession() hook from NextAuth.
Important Files
/lib/auth.tsNextAuth.js configuration. Defines providers, session strategy, and callbacks.
/lib/auth-utils.tsServer-side authentication helpers: requireAuth(), requireEntitlement(), hasEntitlement().
/components/AuthForm.tsxSign-in form UI component. Handles OAuth and magic link flows.
/app/auth/page.tsxAuthentication page that renders the AuthForm component.
/app/api/auth/[...nextauth]/route.tsNextAuth API route handler. Handles OAuth callbacks and session management.
/app/api/auth/magic-link/route.tsMagic link email sender. Generates verification tokens and sends emails.
/app/api/auth/magic-link/verify/route.tsMagic link verification handler. Validates tokens and creates sessions.
Providers
Google OAuth
One-click sign-in using Google accounts. Requires GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.
Flow: User clicks "Continue with Google" → Redirected to Google → Returns to /api/auth/callback/google → Session created → Redirected to dashboard.
Magic Links
Passwordless email authentication. User enters email → Receives verification link → Clicks link → Session created.
Requires RESEND_API_KEY for email delivery. Tokens expire after 24 hours.
Server-Side Usage
Use these functions in Server Components and API routes:
requireAuth()
Returns the authenticated user or redirects to /auth.
import { requireAuth } from "@/lib/auth-utils";
export default async function ProtectedPage() {
const user = await requireAuth();
return <div>Hello, {user.email}</div>;
}requireEntitlement()
Requires authentication and a specific entitlement. Redirects to /pricing if missing.
import { requireEntitlement } from "@/lib/auth-utils";
export default async function ProPage() {
const user = await requireEntitlement("pro_features");
return <ProContent />;
}hasEntitlement()
Checks entitlement without redirecting. Returns boolean.
import { hasEntitlement } from "@/lib/auth-utils";
export default async function Dashboard() {
const hasPro = await hasEntitlement("pro_features");
return hasPro ? <ProDashboard /> : <FreeDashboard />;
}Client-Side Usage
Use the useSession hook from NextAuth in Client Components:
"use client";
import { useSession } from "next-auth/react";
function MyComponent() {
const { data: session, status } = useSession();
if (status === "loading") return <Loading />;
if (!session) return <LoginPrompt />;
return <div>Hello, {session.user.name}</div>;
}For entitlements, use the useEntitlements hook:
"use client";
import { useEntitlements } from "@/hooks/use-entitlements";
function MyComponent() {
const { hasEntitlement, loading } = useEntitlements();
if (loading) return <Spinner />;
if (!hasEntitlement("pro_features")) return <UpgradePrompt />;
return <ProFeature />;
}What You Can Customize
AuthForm Component
Located at /components/AuthForm.tsx. You can customize:
- Styling and layout
- Copy and messaging
- Additional form fields (if needed)
Keep the core authentication logic (OAuth, magic links) intact.
Session Duration
Modify in /lib/auth.ts:
session: {
maxAge: 30 * 24 * 60 * 60, // 30 days
updateAge: 24 * 60 * 60, // 24 hours
}Additional OAuth Providers
Add providers in /lib/auth.ts following the Google provider pattern. NextAuth supports GitHub, Discord, Apple, and many others.
What NOT to Touch
/lib/auth.ts
Core NextAuth configuration. Marked with 🔒 CORE SYSTEM. Only modify session duration or add providers if you understand the implications.
/lib/auth-utils.ts
Authentication helper functions. These ensure consistent behavior across protected routes. Don't modify the core logic.
/app/api/auth/ routes
NextAuth API routes and magic link handlers. These are critical for authentication flow.
Related Sections
- Entitlements - Feature gating system that builds on authentication
- Dashboard - Protected routes and pages
- Email System - Magic link email delivery