Authentication
How login works
Email/password login issues a custom JWT (via jose, not NextAuth) stored in an HttpOnly cookie. Login is rate-limited to 5 attempts per 15 minutes, registration to 5 per hour per IP — both enforced at the database level, no Redis required.
Social login
Google, GitHub, Microsoft, and Facebook OAuth ship out of the box. Unlike most boilerplates, provider credentials are never environment variables — they're entered once in the admin panel, encrypted at rest, and can be toggled on or off without a redeploy.
Roles, not just sessions
Every sensitive request re-checks the caller's role against the database, rather than trusting a role claim baked into the JWT. That closes a common gap: revoking access takes effect on the next request, not after a token expires.
Admin impersonation
An admin can sign a short-lived token to act as another user — useful for support and debugging — and end the session explicitly when done.
Under the hood
Authentication logic is split across four layers with distinct responsibilities: low-level JWT/cookie primitives, a server-component-oriented layer that redirects on failure, an API-route-oriented layer that returns JSON 401/403, and a separate path for AI agent authentication (see AI & Agents).