אימות ב-Next.js 16 עם Auth.js v5 הוא הדרך הרשמית והמומלצת לטיפול במשתמשים ב-App Router. השילוב המנצח: הפונקציה auth() ב-Server Components, proxy.ts להגנה על נתיבים, ו-Server Actions לטפסי התחברות. Auth.js v5 (שמו הקודם NextAuth.js) הוא הפתרון הרשמי המומלץ בתיעוד של Next.js, תומך באופן מלא ב-App Router וב-React 19, ועובד גם ב-Edge Runtime וגם ב-Node.js Runtime. במדריך הזה אסקור הקמה מלאה מ-zero ל-production, כולל JWT לעומת database sessions, OAuth, credentials, והגנת נתיבים.
Auth.js v5 מחליף את getServerSession() בפונקציה אחת, auth(), שעובדת ב-Server Components, ב-Route Handlers, ב-Server Actions וב-proxy.
הקובץ proxy.ts (לשעבר middleware.ts עד Next.js 15) הוא המקום הנכון להגנת נתיבים, אבל עליו לרוץ ב-Edge Runtime ולכן נדרש פיצול הקונפיגורציה.
JWT sessions הם ברירת המחדל ב-2026 בגלל תאימות מלאה ל-Edge. database sessions דורשים adapter (Prisma או Drizzle) ולא ניתן לקרוא להם מ-proxy.
Server Actions עם signIn() ו-signOut() הן הדרך המודרנית לטפסי התחברות, בלי useSession() בצד הלקוח.
קונפיגורציה מינימלית דורשת AUTH_SECRET, ספק אחד לפחות, ופונקציית authorized ב-callbacks להגנת נתיבים מ-proxy.
למה Auth.js v5 ב-Next.js 16
הייתי עם NextAuth.js מאז גרסה 3, כשעוד היה pages/api/auth/[...nextauth].ts ו-getSession() שהחזיר null בלי להסביר למה. גרסה 5, שהפכה ליציבה בסוף 2024 ושופרה משמעותית במהלך 2025 ו-2026, היא קפיצת מדרגה אמיתית. API אחיד, תמיכה מובנית ב-App Router, ועבודה חלקה עם Edge Runtime. אם אתם ב-Next.js 16, אין סיבה לא להשתמש בה.
השינוי המרכזי לעומת v4 הוא איחוד הקונפיגורציה לקובץ auth.ts אחד שמייצא ארבעה דברים: handlers (ל-Route Handlers), auth (לקריאה ל-session מכל מקום), signIn ו-signOut (ל-Server Actions). הפונקציה getServerSession() פשוט נעלמה, וזה דבר טוב. היא הייתה גורם בלבול ענקי בקוד שלי עד היום.
תאימות חשובה: Auth.js v5 עובד עם React 19 ועם Next.js 16 (release notes) ללא תיקונים. כן צריך לזכור שאם השתמשתם ב-middleware.ts בעבר, ב-Next.js 16 הוא קיבל את השם proxy.ts, ויש מדריך מעבר מ-middleware ל-proxy שמראה את ההבדלים המלאים.
התקנה וקונפיגורציה ראשונית
ההתקנה ב-2026 קצרה. צריך חבילה אחת, קובץ קונפיגורציה אחד, וסוד אחד.
הפקודה npx auth secret תוסיף AUTH_SECRET ל-.env.local שלכם. זהו ה-secret שמשמש לחתימה על JWT. אם הוא דולף, כל ה-session tokens שלכם נחשפים, אז אל תכניסו אותו ל-git.
הקובץ הראשי, auth.ts בשורש הפרויקט, נראה ככה במינימום:
// app/api/auth/[...nextauth]/route.ts
export { GET, POST } from "@/auth"
export const runtime = "nodejs" // חשוב: לא edge ברמת ה-route handler
הוספת OAuth providers (Google, GitHub)
OAuth ב-Auth.js v5 הוא ה-flow שהכי קל להפעיל. שלוש שורות לכל provider. ב-Next.js 16, ה-callback URL הוא /api/auth/callback/[provider], וזה הערך שצריך להזין בדשבורד של ה-provider (Google Cloud Console, GitHub Developer Settings וכו').
שימו לב לקונבנציית שמות משתני הסביבה: AUTH_[PROVIDER]_ID ו-AUTH_[PROVIDER]_SECRET. אם תשתמשו בדיוק בשמות האלה, Auth.js יקרא אותם אוטומטית ותוכלו להשמיט את ה-clientId וה-clientSecret מהקונפיגורציה. אני אישית מעדיף לכתוב אותם במפורש כי זה מקל על debugging כשמשהו נשבר ב-CI.
כפתור התחברות הוא Server Action פשוט. בלי useState, בלי fetch, בלי טיפול ב-redirects ידני:
אם אתם מנהלים סיסמאות בעצמכם, וזו תמיד אחריות גדולה, תצטרכו את ה-Credentials provider. הוא לא נתמך עם database sessions בלי תוספות, אבל עם JWT הוא עובד נהדר. הדפוס שאני ממליץ עליו: validation עם zod, השוואת hash עם bcrypt, והחזרת אובייקט user או null.
// auth.ts (חלקי)
import Credentials from "next-auth/providers/credentials"
import { z } from "zod"
import bcrypt from "bcryptjs"
import { getUserByEmail } from "@/lib/users"
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Credentials({
async authorize(credentials) {
const parsed = schema.safeParse(credentials)
if (!parsed.success) return null
const user = await getUserByEmail(parsed.data.email)
if (!user) return null
const ok = await bcrypt.compare(parsed.data.password, user.passwordHash)
if (!ok) return null
return { id: user.id, email: user.email, name: user.name }
},
}),
],
session: { strategy: "jwt" },
})
טופס ההתחברות בצד הלקוח הוא שוב Server Action, בלי "use client" מיותר. השילוב טבעי עם המדריך המלא ל-Server Actions ב-Next.js 16 שמסביר בהרחבה את ה-API החדש של useActionState לטיפול בשגיאות.
הגנת נתיבים היא היכן ש-Auth.js v5 באמת בולט. במקום middleware שקורא לדאטהבייס בכל request (יקר, איטי, בלתי אפשרי ב-Edge), הוא מציע דפוס split config: קונפיג מלא ל-server, קונפיג רזה ל-proxy.
// proxy.ts (ב-Next.js 16, השם החדש של middleware.ts)
import NextAuth from "next-auth"
import { authConfig } from "./auth.config"
export const { auth: middleware } = NextAuth(authConfig)
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}
הקובץ auth.ts המלא מייבא את authConfig ומוסיף providers ו-callbacks כבדים יותר שלא יכולים לרוץ ב-Edge (למשל ה-Credentials עם bcrypt). זה הדפוס הרשמי שמופיע ב-תיעוד הרשמי של Auth.js, וזה גם מה שיגרום למשתמשים מוגנים לא מאומתים לקבל 307 redirect מיידי בלי round trip לדאטהבייס.
JWT לעומת Database Sessions
שאלה חוזרת. הנה ההבדלים בטבלה ברורה:
תכונה
JWT (ברירת מחדל)
Database
ביצועים
ללא קריאה ל-DB ב-proxy
קריאה לכל request
Edge Runtime
תומך מלא
לא נתמך ב-proxy
ביטול session מיידי
קשה (צריך blacklist)
קל (מחיקה מה-DB)
גודל cookie
גדל עם data
קטן (id בלבד)
תאימות Credentials
תמיכה מלאה
נדרשת התאמה
שמירת user data רגיש
חשוף בצד לקוח
נשאר ב-server
שורה תחתונה: התחילו עם JWT אלא אם יש לכם דרישה ספציפית לביטול sessions באופן מיידי (למשל banking או admin tools). פעם אחת עברתי אפליקציה מ-JWT ל-database sessions אחרי שהיה לנו אירוע אבטחה, וזה היה כאב ראש של שבועיים. אם אתם בונים מאפס ויש לכם שום ספק, JWT הוא הבחירה הנכונה ב-2026.
קריאה ל-session ב-React Server Components
בעולם ה-App Router, רוב הזמן אתם רוצים לקרוא session ב-Server Component, לא בצד הלקוח. ה-API פשוט להחריד:
// app/dashboard/page.tsx
import { auth } from "@/auth"
import { redirect } from "next/navigation"
export default async function DashboardPage() {
const session = await auth()
if (!session?.user) {
redirect("/login")
}
return (
<div>
<h1>שלום, {session.user.name}</h1>
<p>Email: {session.user.email}</p>
</div>
)
}
הפונקציה auth() פנימית מבצעת deduplication דרך ה-cache של React 19, כך שגם אם תקראו לה ב-10 קומפוננטות, יש רק קריאה אחת לפיצוח ה-JWT לכל request. אין צורך ב-Context, אין צורך ב-Provider, ואין hydration mismatch. זה אחד הדברים שגרמו לי סוף סוף לחבב את ה-App Router אחרי שנים של עבודה עם pages router.
לעדכון session בעקבות שינוי נתונים (למשל אחרי עדכון פרופיל), השתמשו ב-callback jwt כדי לרענן את ה-token, ובצד הלקוח קראו ל-useSession() עם update(). לעבודה עם נתונים שמשתנים תכופות, כמו תפקידי משתמש, שילוב נכון של auth עם Cache Components ו-cacheTag ב-Next.js 16 נותן ביצועים מצוינים.
צ'קליסט production
לפני שדוחפים ל-production, עברו על הרשימה הקצרה הזו. ראיתי כל אחד מהפריטים האלה נופל בפועל באפליקציות חיות:
AUTH_SECRET: לפחות 32 בתים אקראיים, יוצר ב-npx auth secret. שונה לחלוטין בין סביבות.
AUTH_URL או AUTH_TRUST_HOST=true: נדרש מאחורי reverse proxy כמו Vercel או Cloudflare כדי שה-callbacks יבנו URL נכון.
HTTPS בלבד: cookies של session מסומנים כ-Secure ב-production. בדיקה ב-HTTP פשוט לא תעבוד.
Cookie SameSite: ברירת המחדל היא lax. אם אתם משלבים iframes או cross-domain, תצטרכו none בתוספת שיקולי CSRF נוספים.
CSRF protection: מובנה ב-Auth.js, אבל אם אתם פותחים endpoints מותאמים אישית, ודאו שיש להם הגנת CSRF נפרדת או שהם דורשים SameSite=lax.
Rate limiting על Credentials: הסיוט של brute force. שלבו עם Upstash Redis או דומה ב-proxy לפני שאתם מגיעים ל-signIn().
Database adapter ב-Node runtime בלבד: אם אתם משתמשים ב-Prisma או Drizzle, ה-Route Handlers שלהם חייבים export const runtime = "nodejs".
שאלות נפוצות
האם Auth.js v5 מוכן ל-production ב-2026?
כן. הגרסה הראשונה היציבה של v5 פורסמה בסוף 2024, ומאז 2025 היא מטופלת באפליקציות גדולות כולל באתרים של Vercel עצמה. עדיין מומלץ לעגן גרסת patch ספציפית כי קצב השינויים גבוה מ-v4.
מה ההבדל בין Auth.js ל-NextAuth.js?
זה אותו פרויקט. NextAuth.js v4 שונה שמו ל-Auth.js בגרסה v5 כדי לציין שהוא תומך גם ב-frameworks אחרים (SvelteKit, SolidStart, Express). בעולם של Next.js, חבילת ה-npm עדיין נקראת next-auth.
איך מגנים על נתיבים ב-Next.js 16 בלי middleware?
ב-Next.js 16, הקובץ middleware.ts שונה שמו ל-proxy.ts. הוא רץ ב-Edge Runtime וקורא ל-auth() מתוך Auth.js עם split config כדי להחליט אם לתת גישה. נתיבים מוגנים מקבלים 307 redirect ל-/login.
האם Auth.js עובד עם Server Actions?
כן, ולמעשה זו הדרך המומלצת ב-2026. הפונקציות signIn() ו-signOut() מ-auth.ts מיועדות לשימוש ישיר בתוך Server Actions, ללא צורך ב-useSession() או fetch ל-API route ידני.
Auth.js או Clerk או Lucia, איזה לבחור?
Auth.js הוא חינמי ושולט בכל הקוד, אבל דורש קצת עבודה. Clerk הוא מנוהל, עם ממשק יפה, ויקר. Lucia היה סופר רזה אבל התחזוקה הופסקה בסוף 2024 ולא מומלץ לפרויקטים חדשים. ב-2026, Auth.js היא ברירת המחדל הסבירה אלא אם אתם מוכנים לשלם על UX מנוהל מלא.