Next.js Authentication Tutorial: Complete Guide 2026
Key Insight
NextAuth.js (now Auth.js) is the standard authentication solution for Next.js applications. It supports OAuth providers like Google and GitHub, email/password login, magic links, and custom credentials. This tutorial covers setup, configuration, protected routes, and API route protection.
Introduction
Authentication is essential for any application with user accounts. Next.js combined with NextAuth.js provides a robust, secure, and flexible authentication solution that works with the App Router, Server Components, and API routes.
This tutorial covers implementing authentication from scratch, including OAuth providers, credentials-based login, and protecting routes.
Prerequisites
- Next.js 14+ application
- Basic React and Next.js knowledge
- Node.js 18+
Installation
Install NextAuth.js (now called Auth.js) using npm or yarn. You will also need any database adapters if using database sessions.
Create the necessary environment variables for your secret key and OAuth provider credentials.
Basic Setup
Create Auth Configuration
Create an auth configuration file that defines your providers and callbacks. This is where you configure how authentication works in your application.
Set Up API Route
Create the NextAuth API route handler. This handles all authentication endpoints like sign in, sign out, and callbacks.
Add Session Provider
Wrap your application with the SessionProvider to make authentication state available throughout your app.
OAuth Providers
Google Sign-In
Google OAuth is one of the most popular authentication methods. Configure it by:
- Create a project in Google Cloud Console
- Enable the OAuth 2.0 API
- Create OAuth credentials
- Add authorized redirect URIs
- Add client ID and secret to environment variables
GitHub Sign-In
GitHub OAuth is popular for developer-focused applications:
- Create an OAuth App in GitHub Developer Settings
- Set the authorization callback URL
- Add client ID and secret to environment variables
Credentials Provider
For email/password authentication, use the Credentials provider. This requires:
- A user database
- Password hashing (use bcrypt)
- Custom authorize function
The authorize function receives credentials and should:
- Look up the user by email
- Verify the password hash
- Return the user object or null
Important: Handle errors securely without revealing whether the email exists.
Protecting Routes
Client-Side Protection
Use the useSession hook to check authentication status and redirect unauthorized users.
Server-Side Protection
For Server Components, use getServerSession to check authentication. This is more secure as it runs on the server.
Middleware Protection
Create a middleware.ts file to protect entire route groups. This runs before requests reach your pages.
Configure which routes require authentication using the matcher pattern.
Customizing Pages
Custom Sign-In Page
Create a custom sign-in page for better UX. Configure NextAuth to use your custom page instead of the default.
Your custom page should include forms for each provider and handle errors appropriately.
Custom Error Page
Handle authentication errors gracefully with a custom error page that explains what went wrong.
Session Management
Accessing Session Data
On the client, use the useSession hook. It returns session data, loading status, and update function.
On the server, use getServerSession. This is secure and can be used in Server Components and API routes.
Extending Session Data
Add custom fields to the session by extending the callbacks. For example, add user role or ID.
Database Adapters
For persistent sessions and user storage, use a database adapter.
Popular options:
- Prisma: Works with many databases
- Drizzle: Lightweight, TypeScript-first
- MongoDB: For document-based storage
The adapter handles user creation, session storage, and account linking.
Security Best Practices
Environment Variables
Never commit secrets to version control. Use environment variables for:
- NEXTAUTH_SECRET (generate with openssl rand -base64 32)
- OAuth client IDs and secrets
- Database connection strings
CSRF Protection
NextAuth includes CSRF protection by default. Do not disable it.
Secure Cookies
In production, cookies are automatically set to secure and httpOnly. Verify your deployment uses HTTPS.
Rate Limiting
Add rate limiting to authentication endpoints to prevent brute force attacks.
Testing
Development Testing
Use test accounts for OAuth providers during development. Most providers have sandbox modes.
E2E Testing
For end-to-end tests, mock the session provider or use test credentials. Playwright and Cypress both support this.
Deployment
Ensure your production environment has:
- NEXTAUTH_URL set to your production URL
- NEXTAUTH_SECRET as a strong random string
- OAuth callback URLs updated for production
- Database connection string for production database
Conclusion
NextAuth.js provides a comprehensive authentication solution for Next.js applications. Start with OAuth providers for quick implementation, add credentials if needed, and protect your routes appropriately.
Focus on security from the start—use environment variables, enable CSRF protection, and implement rate limiting. The library handles most security concerns, but understanding the underlying mechanisms helps you make better decisions.
Key Takeaways
- NextAuth.js handles OAuth, credentials, and magic links
- Configure providers in your auth options file
- Use useSession hook for client-side auth state
- Protect routes with middleware or getServerSession
- Store sessions in JWT or database depending on needs
- Customize sign-in pages for better UX
Frequently Asked Questions
Is NextAuth.js free to use?
Yes, NextAuth.js is completely free and open source. The only costs are for any external services you use, like databases for session storage or email providers for magic links. OAuth providers like Google and GitHub are also free for authentication.
Should I use JWT or database sessions?
JWT sessions are stateless and work well for simple applications without a database. Database sessions are better when you need to revoke sessions, track active sessions, or store additional user data. For most applications, JWT is simpler to start with.
How do I protect API routes in Next.js?
Use getServerSession in API routes to check authentication. If no session exists, return a 401 status. For middleware-based protection, use the middleware.ts file to check authentication before requests reach your routes.