useSession() returns { data: undefined, status: 'unauthenticated' } despite a valid sign-inappears when:After deploying a Next.js app with NextAuth or Auth.js v5 when useSession returns undefined on production but data and status are correct locally
NextAuth session undefined in production
Auth.js is environment-sensitive. Missing NEXTAUTH_URL, wrong NEXTAUTH_SECRET, or absent SessionProvider all produce the same symptom: the session hook sees nothing.
NEXTAUTH_URL to your production domain, set NEXTAUTH_SECRET to a persistent openssl rand -base64 32 value, and wrap your app in <SessionProvider> inside the root layout.Quick fix for NextAuth session undefined
01// app/layout.tsx — wrap the app in SessionProvider (client component)02import { SessionProvider } from "next-auth/react";03import { auth } from "@/auth"; // your NextAuth config04 05export default async function RootLayout({ children }: { children: React.ReactNode }) {06 const session = await auth();07 return (08 <html lang="en">09 <body>10 <SessionProvider session={session}>{children}</SessionProvider>11 </body>12 </html>13 );14}15 16// .env.production — all three must be set on Vercel17// NEXTAUTH_URL=https://myapp.com18// NEXTAUTH_SECRET=<paste openssl rand -base64 32 output>19// AUTH_TRUST_HOST=true # Auth.js v5 — optional when NEXTAUTH_URL is set20 21// auth.ts — Auth.js v5 canonical config22// import NextAuth from "next-auth";23// import Google from "next-auth/providers/google";24// export const { auth, handlers, signIn, signOut } = NextAuth({25// providers: [Google],26// trustHost: true,27// });Deeper fixes when the quick fix fails
01 · Auth.js v5 — move to the auth() helper in server components
01// app/dashboard/page.tsx — server component reads session without useSession02import { auth } from "@/auth";03import { redirect } from "next/navigation";04 05export default async function DashboardPage() {06 const session = await auth();07 if (!session?.user) redirect("/sign-in");08 09 return <div>Welcome, {session.user.email}</div>;10}11 12// auth.ts13import NextAuth from "next-auth";14import Google from "next-auth/providers/google";15 16export const { auth, handlers, signIn, signOut } = NextAuth({17 providers: [Google],18 trustHost: true,19 session: { strategy: "jwt" },20});02 · Cookie Secure flag on HTTP preview URLs
If you self-host and serve preview deployments over HTTP, the default __Secure- prefixed cookie never sets because browsers require HTTPS. Disable the prefix in development by setting useSecureCookies: false in your Auth.js config when NODE_ENV !== "production". Do not disable in real production — the Secure flag is a real XSS defense.
01// auth.ts — opt out of Secure cookies only in dev02export const { auth, handlers } = NextAuth({03 providers: [Google],04 trustHost: true,05 useSecureCookies: process.env.NODE_ENV === "production",06});03 · Persist secrets correctly in Vercel env
01# 1. generate a secret locally02openssl rand -base64 3203 04# 2. set in Vercel — once, never rotate without a plan05# Dashboard → Settings → Environment Variables → Add06# NEXTAUTH_URL https://myapp.com Production07# NEXTAUTH_SECRET <paste the base64 string> Production, Preview08# AUTH_TRUST_HOST true Preview09# GOOGLE_CLIENT_ID ... Production, Preview10# GOOGLE_CLIENT_SECRET ... Production, Preview11 12# 3. redeploy to pick up the change13vercel deploy --prodWhy AI-built apps hit NextAuth session undefined
Auth.js (the v5 rebrand of NextAuth) relies on three pieces to rehydrate a session client-side. First, a JWT cookie signed with NEXTAUTH_SECRET. Second, a <SessionProvider> React context that polls the session endpoint. Third, an accurate NEXTAUTH_URL so the provider knows where to call. Break any one and useSession() returns { data: undefined, status: 'unauthenticated' } with no error shown to the user.
AI builders scaffold NextAuth with the quickstart that assumes a local dev setup. They set NEXTAUTH_SECRET in a .env.local that never gets committed, and assume NEXTAUTH_URL defaults to http://localhost:3000. At deploy on Vercel, neither env var exists in the project settings. Auth.js either throws a quiet error in the server log (which the user never sees) or refuses to sign JWTs. The sign-in flow appears to succeed — the provider redirects, the cookie is set — but the JWT has no valid signature or the callback URL points at localhost and the session never rehydrates.
The second pattern is a regenerated secret. Some teams put NEXTAUTH_SECRET in a GitHub Action that rotates on every deploy. Each rotation invalidates every JWT in circulation. Users see themselves logged in for a millisecond, then logged out. The fix is to treat the secret as a fixed production credential managed in Vercel env, not in CI. Rotating it requires planned downtime and user re-sign-in.
The third pattern is missing SessionProvider. The hook throws no error when context is missing — it returns undefined. AI-generated App Router code sometimes forgets to add the provider because it was a Pages Router pattern. Add it to app/layout.tsx wrapped around {children}, pre-fetching the session on the server so the client has data on first paint.
NextAuth session undefined by AI builder
How often each AI builder ships this error and the pattern that produces it.
| Builder | Frequency | Pattern |
|---|---|---|
| Lovable | Every NextAuth scaffold | Skips NEXTAUTH_SECRET in Vercel env — dev-only .env.local |
| Bolt.new | Common | Puts SessionProvider inside a client component instead of root layout |
| v0 | Common | Hardcodes NEXTAUTH_URL=http://localhost:3000 into next.config |
| Cursor | Sometimes | Regenerates NEXTAUTH_SECRET in CI — invalidates every session on every deploy |
| Replit Agent | Rare | Overrides cookie.domain explicitly — breaks on Vercel preview URLs |
Related errors we fix
Stop NextAuth session undefined recurring in AI-built apps
- →Set NEXTAUTH_URL and NEXTAUTH_SECRET in Vercel project env at the moment you create the project.
- →Generate NEXTAUTH_SECRET once with openssl rand -base64 32 and never rotate without a plan.
- →Put SessionProvider in app/layout.tsx, pre-fetching the session on the server.
- →Use Auth.js v5 auth() helper in server components — avoids the client-side hook entirely.
- →Playwright-test the sign-in flow on production and preview URLs for every deploy.
Still stuck with NextAuth session undefined?
NextAuth session undefined questions
Why does useSession return undefined only in production?+
Do I need NEXTAUTH_URL if I use AUTH_TRUST_HOST?+
What goes in NEXTAUTH_SECRET and why does it have to persist?+
Why does the session cookie not set on my Vercel preview URL?+
How long does a NextAuth session fix take?+
Ship the fix. Keep the fix.
Emergency Triage restores service in 48 hours. Break the Fix Loop rebuilds CI so this error cannot ship again.
Hyder Shah leads Afterbuild Labs, shipping production rescues for apps built in Lovable, Bolt.new, Cursor, Replit, v0, and Base44. our rescue methodology.