NextAuth is a great tool when you need OAuth providers or a database-backed session store. But for simple admin-only auth or projects where you control all credentials, a custom JWT solution is significantly simpler and easier to reason about.
The Core Pieces
You need four things: a login route that verifies credentials and sets an httpOnly cookie, a JWT utility that signs and verifies tokens, a middleware that protects admin routes by reading the cookie, and a logout route that clears the cookie. That's it.
httpOnly Cookies vs localStorage
Never store JWTs in localStorage. An XSS vulnerability anywhere in your app gives an attacker full access to any localStorage value. httpOnly cookies are not accessible to JavaScript at all — they're only sent automatically on HTTP requests, making XSS unable to exfiltrate them.
Middleware-Based Route Protection
Next.js middleware runs on the Edge before the page renders, making it the ideal place to verify the session cookie. Redirect to /auth/login if no valid token is present. This keeps protection centralized and impossible to forget on individual pages.