How to Add Authentication to Any App (2026 Guide)
Authentication is the first feature every app needs and the last one you want to build from scratch. In 2026, you have excellent options ranging from drop-in managed services to open-source libraries. Here's how to choose and implement.
Choose Your Approach
| Approach | Time to Implement | Monthly Cost | Control |
|---|---|---|---|
| Managed service (Clerk, Auth0) | 1-2 hours | $0-25+ | Low |
| Open-source library (Better Auth, NextAuth) | 2-8 hours | $0 | High |
| BaaS auth (Supabase, Firebase) | 1-3 hours | $0 (included) | Medium |
| Build from scratch | 1-2 weeks | $0 | Full |
Recommendation: Unless you have specific security requirements that demand custom auth, use a managed service or open-source library. Auth is a solved problem — solve your actual business problem instead.
Option 1: Managed Services (Fastest)
Clerk (Recommended for Next.js)
npm install @clerk/nextjs
// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'
export default function Layout({ children }) {
return (
<ClerkProvider>
<html><body>{children}</body></html>
</ClerkProvider>
)
}
// middleware.ts
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
// app/page.tsx
import { SignInButton, SignedIn, SignedOut, UserButton } from '@clerk/nextjs'
export default function Home() {
return (
<>
<SignedOut><SignInButton /></SignedOut>
<SignedIn><UserButton /><p>You're signed in!</p></SignedIn>
</>
)
}
That's it. Email/password, Google, GitHub — all working. User management dashboard included.
Free tier: 10,000 MAUs. Paid: $25/mo + $0.02/MAU.
Read our full comparison: Clerk vs Auth0 vs NextAuth →
Auth0 (Enterprise-Ready)
Auth0 provides a Universal Login page that handles all auth flows:
npm install @auth0/nextjs-auth0
// app/api/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0'
export const GET = handleAuth()
// app/layout.tsx
import { UserProvider } from '@auth0/nextjs-auth0/client'
export default function Layout({ children }) {
return <UserProvider>{children}</UserProvider>
}
Free tier: 7,500 MAUs. Paid: Custom pricing.
Option 2: Open-Source Libraries (More Control)
Better Auth (Recommended for Full Control)
Better Auth gives you a complete auth system without vendor lock-in.
npm install better-auth
// lib/auth.ts
import { betterAuth } from 'better-auth'
export const auth = betterAuth({
database: { provider: 'pg', url: process.env.DATABASE_URL },
emailAndPassword: { enabled: true },
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
})
// Client usage
import { createAuthClient } from 'better-auth/react'
const { signIn, signUp, signOut, useSession } = createAuthClient()
// Sign up
await signUp.email({ email: 'user@example.com', password: 'password', name: 'User' })
// Sign in
await signIn.email({ email: 'user@example.com', password: 'password' })
// Google sign in
await signIn.social({ provider: 'google' })
Cost: Free forever. Self-hosted.
Read our full comparison: Better Auth vs Lucia vs NextAuth →
NextAuth (Auth.js) — The Established Choice
npm install next-auth
// auth.ts
import NextAuth from 'next-auth'
import Google from 'next-auth/providers/google'
import GitHub from 'next-auth/providers/github'
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Google({ clientId: process.env.GOOGLE_ID!, clientSecret: process.env.GOOGLE_SECRET! }),
GitHub({ clientId: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET! }),
],
})
Cost: Free. Open-source.
Option 3: BaaS Auth (If You're Already Using One)
Supabase Auth
If you're using Supabase for your database, auth is included:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(url, anonKey)
// Sign up
await supabase.auth.signUp({ email: 'user@example.com', password: 'password' })
// Sign in
await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'password' })
// OAuth
await supabase.auth.signInWithOAuth({ provider: 'google' })
// Get session
const { data: { session } } = await supabase.auth.getSession()
Firebase Auth
import { getAuth, signInWithEmailAndPassword, GoogleAuthProvider, signInWithPopup } from 'firebase/auth'
const auth = getAuth()
// Email/password
await signInWithEmailAndPassword(auth, email, password)
// Google
const provider = new GoogleAuthProvider()
await signInWithPopup(auth, provider)
Setting Up OAuth Providers
Regardless of which auth solution you choose, you'll need OAuth credentials.
Google OAuth Setup
- Go to Google Cloud Console
- Create or select a project
- Enable the Google+ API (or People API)
- Go to Credentials → Create Credentials → OAuth Client ID
- Set authorized redirect URIs (your auth callback URL)
- Copy Client ID and Client Secret
GitHub OAuth Setup
- Go to GitHub Settings → Developer Settings → OAuth Apps
- Click "New OAuth App"
- Set Authorization callback URL
- Copy Client ID and Client Secret
Apple Sign-In Setup
- Apple Developer Account required ($99/year)
- Create a Services ID in Certificates, Identifiers & Profiles
- Enable Sign In with Apple
- Configure return URLs
- Generate a client secret (JWT)
Security Checklist
Before going to production:
- HTTPS only — Never send credentials over HTTP
- Password hashing — Use bcrypt, scrypt, or Argon2 (managed services handle this)
- Rate limiting — Prevent brute force on login endpoints
- CSRF protection — Use CSRF tokens for form-based auth
- Session management — Secure, HttpOnly, SameSite cookies
- Password requirements — Minimum 8 characters, check against breached passwords
- Email verification — Verify email addresses before granting full access
- Account lockout — Lock after N failed attempts (with time-based reset)
- Secure password reset — Time-limited, single-use tokens
- MFA option — Offer 2FA for sensitive applications
Decision Framework
Use Clerk if:
- Building with Next.js
- Want the fastest implementation
- Need pre-built UI components
- Budget for $25+/month at scale
Use Better Auth if:
- Want full control and no vendor lock-in
- Comfortable with self-hosting
- Need features beyond basic auth (organizations, 2FA)
- Want to keep costs at zero
Use NextAuth if:
- Primarily need OAuth/social login
- Want the largest community
- Building with Next.js (App Router or Pages)
- Don't need email/password (or can accept its limitations)
Use Supabase/Firebase Auth if:
- Already using that platform for your database
- Want auth integrated with your data layer
- Don't want to manage a separate auth service
Build from scratch only if:
- You have specific regulatory requirements (HIPAA, SOC2)
- None of the above solutions work for your architecture
- You have security expertise on your team
- You enjoy pain (kidding, but seriously — use a library)
FAQ
Is it safe to use a managed auth service?
Yes. Clerk, Auth0, and Supabase Auth have security teams dedicated to auth. They're likely more secure than what you'd build yourself, unless you're a security expert.
How do I add auth to an existing app?
Same process — install the library, wrap your app with the provider, protect routes with middleware or guards. Most solutions support incremental adoption.
Should I use JWT or session-based auth?
Session-based (database) is generally more secure (revocable, no token theft issues). JWT is simpler for stateless architectures. Most managed services abstract this decision away.
How long does migration between auth providers take?
Plan for 1-2 weeks. The hardest part is migrating user passwords (you can't — users will need to reset passwords unless the old provider exports hashes in a compatible format).
The Bottom Line
- Using Next.js? → Clerk (managed) or Better Auth (self-hosted)
- Using Supabase? → Supabase Auth (it's included)
- Using Firebase? → Firebase Auth (it's included)
- Other framework? → Better Auth or Auth0
- Building from scratch? → Don't, unless you have a specific reason
Auth should take hours to implement, not weeks. Choose a solution and move on to building your actual product.