NextAuth Checklist: 8 Things Before Going to Production
I’ve seen 5 production deployments go sideways this month. All 5 made the same mistakes regarding their NextAuth checklist.
1. Secure Your Callback URL
Never underestimate the importance of securing your callback URL. If an attacker can hijack your authentication flow, they potentially gain access to sensitive user data.
const options = {
providers: [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackUrl: 'https://yourdomain.com/api/auth/callback/google'
})
],
// security settings
pages: {
signIn: '/auth/signin',
error: '/auth/error'
}
}
If you skip this, you risk exposing your application to phishing attacks or redirect vulnerabilities.
2. Configure Environment Variables
Your environment variables must be on point. This isn’t just about convenience; exposing secrets can lead to significant data breaches.
# .env
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
NEXTAUTH_SECRET=your_secret
Failing to set these variables correctly might send your app crashing into the production abyss.
3. Enable HTTPS
If your app isn’t running over HTTPS in production, please stop right there. Data can be intercepted over HTTP, making your authentication flow vulnerable.
// In your Next.js configuration
module.exports = {
images: {
domains: ['yourdomain.com'],
},
async redirects() {
return [
{
source: '/:path*/',
destination: 'https://yourdomain.com/:path*/',
permanent: true,
},
]
},
}
Skipping HTTPS means you’re inviting trouble; expect to deal with angry users whose data you’ve compromised.
4. Set Up Database Sessions
Using database sessions retains user state and allows you to manage user sessions effectively. It’s essential for scalability.
import NextAuth from 'next-auth'
import { MongoDBAdapter } from '@next-auth/mongodb-adapter'
import clientPromise from '../../../lib/mongodb'
export default NextAuth({
adapter: MongoDBAdapter(clientPromise),
// Other NextAuth options
})
If you opt out of this, you’ll have a nightmare managing user sessions, leading to lost state across multiple tabs or devices.
5. Validate User Input
Never, and I mean never, trust user input blindly. This is a basic security principle that can save your application from SQL injection attacks and other vulnerabilities.
const { body, validationResult } = require('express-validator');
app.post('/api/auth/signup', [
body('email').isEmail(),
body('password').isLength({ min: 6 })
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// proceed with user creation
});
Ignoring input validation might result in a flawed app that’s easy to exploit. You don’t want to be that guy.
6. Implement CSRF Protection
Cross-site request forgery (CSRF) can take your NextAuth implementation from secure to compromised in a heartbeat. You must have CSRF protection enabled for user sessions.
const options = {
providers: [ /* providers */ ],
session: {
jwt: true,
},
callbacks: {
async jwt(token, user) {
if (user) {
token.id = user.id;
}
return token;
},
async session(session, token) {
session.user.id = token.id;
return session;
},
},
csrf: {
cookie: {
secure: true // Enforce so that's protected
}
}
}
Bypassing CSRF precautions turns your secure application into an easy target for attacks, which is just bad news.
7. Use Rate Limiting
Rate limiting protects against brute-force attacks on your authentication endpoints. Without it, you leave yourself vulnerable.
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/auth/', limiter);
If this isn’t in place, your app could easily become a victim of denial-of-service attacks, no thanks to your carelessness.
8. Monitor Authentication Events
This is more of a nice-to-have but worthy of discussion. Monitoring authentication events helps detect breaches and other anomalies in real-time.
import { createLogger, format, transports } from 'winston';
const logger = createLogger({
level: 'info',
format: format.json(),
transports: [new transports.Console()]
});
// Log successful logins
app.post('/api/auth/signin', (req, res) => {
// authenticate user
logger.info(`User ${req.body.email} logged in successfully.`);
});
Skipping this means you’re left in the dark until something goes wrong. Trust me, I’ve been there, staring at the logs wondering what happened.
Priority Order
Here’s how I would prioritize these items:
- Do This Today: Secure Your Callback URL, Configure Environment Variables, Enable HTTPS, Set Up Database Sessions
- Nice to Have: Validate User Input, Implement CSRF Protection, Use Rate Limiting, Monitor Authentication Events
Tools Table
| Feature | Tool/Service | Cost | Notes |
|---|---|---|---|
| Environment Variable Management | dotenv | Free | Basic environment variable management. |
| Rate Limiting | express-rate-limit | Free | Simple installation for Express. |
| Logger | winston | Free | Very flexible and powerful logger. |
| Database Sessions | MongoDB Adapter | Variable depending on hosting | Essential for user state persistence. |
| Performance Monitoring | Sentry | Free tier available | Detects errors and provides performance metrics. |
The One Thing
If you only do one thing from this NextAuth checklist, make it securing your callback URL. It prevents a wide array of issues including session hijacking and keeps your application’s integrity intact. Trust me; you’ll thank yourself later.
FAQ
Why is securing the callback URL crucial?
It acts as the entry point for your authentication flow. If not secured, attackers can redirect users elsewhere and collect credentials.
Can I skip environment variables for a quicker setup?
Definitely not. Hardcoding sensitive information opens your app to serious vulnerabilities.
What’s the biggest mistake I can make when deploying?
Neglecting HTTPS. Users will abandon your app if they see that dreaded ‘Not Secure’ message.
Are rate limiting and monitoring really necessary?
Absolutely. They save you from dozens of headaches and help catch issues before they escalate.
Why bother with CSRF protection?
CSRF attacks can silently hijack users’ actions. Protecting your sessions should be a priority.
Data Sources
Information gathered from:
Last updated April 30, 2026. Data sourced from official docs and community benchmarks.
🕒 Published: