I used to reach for NextAuth on every project by default.
Then I built a few dashboards where I needed full control over the token — custom claims, a specific cookie strategy, no extra abstraction layer to fight with. Rolling my own JWT auth turned out simpler than expected, and it's what I use now unless a client specifically wants OAuth providers out of the box.
Here's the exact setup.
1. The Auth Helpers
// lib/auth.ts






