One auth() works everywhere
Auth.js v5 (formerly NextAuth.js) ships a single auth() helper that runs in Server Components, Server Actions, Route Handlers, and the proxy. The mental model: "is there a session?" — same answer, same call site, no matter where you ask.
Setup
Install next-auth@beta, configure providers, export handlers + auth. Wire handlers as a Route Handler at app/api/auth/[...nextauth]/route.ts.
Where you'll call auth()
| Location | Pattern |
|---|---|
| Server Component | const session = await auth(); |
| Server Action | same |
| Route Handler | same |
| Proxy | wrap export: export const proxy = auth(req => { … }); |
Centralize Auth.js configuration and use auth() at every server boundary that needs a session. Treat the session as identity evidence, then perform resource-level authorization close to the read or write. Keep provider secrets and callbacks server-only. A shared auth helper still needs failure behavior tailored to each execution surface. Navigation, API calls, and server actions cannot all return a login page without breaking their client contracts.
A session check is not an authorization policy. A signed-in user may still be unable to read another account or mutate an administrative resource. A redirect in Proxy also cannot protect a Route Handler or Server Action called directly. Exercise signed-out, ordinary-user, owner, and administrator cases against the page and the underlying action or handler. Test expired sessions and callback failures, and verify logs do not expose tokens, provider payloads, or secrets.