Authentication
How authentication works in SaaS Template.
Overview
Authentication is handled by NextAuth v5 (Auth.js) with JWT sessions. The configuration lives in src/lib/auth/config.ts.
Supported providers
- Email / password — Bcrypt-hashed passwords stored in the
userstable - Google OAuth — Requires
AUTH_GOOGLE_IDandAUTH_GOOGLE_SECRET - GitHub OAuth — Requires
AUTH_GITHUB_IDandAUTH_GITHUB_SECRET
Environment variables
AUTH_SECRET= # openssl rand -base64 32
AUTH_GOOGLE_ID=
AUTH_GOOGLE_SECRET=
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=
NEXTAUTH_URL=http://localhost:3000
Email verification
After registration, users receive a verification email. Unverified users can still log in but see a banner prompting them to verify. The verification token is stored in verification_tokens and expires after 24 hours.
Password reset
The forgot-password flow sends a time-limited reset link to the user's email. Tokens are stored in the users table (resetToken + resetTokenExpiresAt).
Session data
The JWT session includes:
{
id: string
email: string
role: 'USER' | 'ADMIN'
subscriptionStatus: string | null
subscriptionPlan: string | null
emailVerified: boolean
onboardingCompleted: boolean
}
Protecting routes
Routes are protected in src/middleware.ts. Any path under /dashboard, /billing, /settings, /onboarding, or /referral requires an active session.
To protect an API route manually:
import { auth } from '@/lib/auth'
export async function GET() {
const session = await auth()
if (!session?.user?.id) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
// ...
}