Every NestJS project has this moment. Sign-up and sign-in work. Password hashing works. A JWT gets issued, a guard checks it, and everyone moves on to the parts of the product that actually matter. Then, a few months in, someone asks for Google sign-in, or that users need to be able to change or reset their password, or sign in with a one-time code instead, or that a stateless JWT isn't enough anymore, sessions need to be revocable. And the auth code, the part everyone assumed was finished, turns out to be the part nobody wants to touch.

This post is about why that happens, using the code that actually causes it, and what changes when the auth layer is built to expect it.

Three ways to avoid writing it, each with a real cost

Before getting to the code: not everyone writes auth by hand, and it's worth being honest about why.

Managed services like Auth0 or Clerk get a working sign-in flow running in an afternoon. The cost shows up later: your user data lives on someone else's infrastructure, and the day a requirement doesn't fit their model, you're waiting on their roadmap, not shipping your own fix.