הרסתי את ה-Next.js Auth Matcher שלי שלוש פעמים
הרסתי שלושה פרויקטים לפני שהבנתי איך proxy.ts עובד ב-Next.js 16.
השגיאה הייתה שקטה. בלי לוגים. בלי אזהרות. בלי שגיאות. רק הפניות (redirects) שבורות ופרצות אבטחה.
אם אתם משדרגים ל-Next.js 16, אל תריצו סתם codemod ותמשיכו הלאה. אתם חייבים לבדוק את שלושת הדברים האלה.
מלכודת המעבר
Next.js שינתה את השם של middleware.ts ל-proxy.ts. זה לא רק שינוי שם.
middleware.tsרץ על ה-Edge runtime. הייתה לו תמיכה מוגבלת ב-crypto.proxy.tsרץ על ה-Node.js runtime כברירת מחדל. יש לו תמיכה מלאה ב-crypto.
אם תעדכנו את החבילה (package) באופן ידני ללא codemod, הקובץ הישן middleware.ts שלכם עשוי עדיין להתקיים. הוא יתקמפל מצוין. הוא יעבור את בדיקות ה-TypeScript. אבל הוא לא יעשה כלום. הנתיבים (routes) שלכם לא ייעצרו, וההפניות (redirects) שלכם לא יופעלו.
בדקו את שלושת הדברים האלה באופן ידני:
proxy.tsחייב להימצא בשורש הפרויקט (project root).- הפונקציה המיוצאת (exported function) חייבת להיקרא
proxy. - חייבים למחוק את
middleware.ts.
פער ה-Matcher
ה-matcher הוא המקום שבו הגדרות auth נכשלות הכי הרבה פעמים.
אם ה-matcher שלכם רחב מדי, ה-proxy ירוץ על כל קובץ CSS ותמונה. זה גורם ללולאות הפניה (redirect loops) אינסופיות.
אם ה-matcher שלכם צר מדי, אתם יוצרים פרצת אבטחה.
אם נתיב (route) לא נמצא ב-matcher שלכם, ה-proxy לעולם לא ירוץ. משתמש יכול לשלוח כותרות (headers) משלו לאותו נתיב. אם ה-Server Component שלכם סומך על הכותרות האלה, תוקף יכול להתחזות לכל אחד.
הפתרון: אל תסמכו על כותרות
למדתי את זה בדרך הקשה: אל תסתמכו אך ורק על כותרות (headers) המועברות על ידי ה-proxy.
השתמשו בגישה של שתי שכבות:
- ה-proxy פועל כשער מהיר בגבול הרשת (network boundary).
- ה-Server Component מאמת את ה-JWT ישירות מה-cookie בזמן הרינדור (render time).
הבדיקה השנייה הזו סוגרת את הפער. גם אם ה-matcher מפספס נתיב, ה-Server Component יתפוס את המשתמש הלא תקף. זה מוסיף כמה מילישניות של השהיה (latency), אבל מונע כשל אבטחה מסיבי.
רשימת בדיקה מסכמת:
- השתמשו ב-
proxy.tsעבור auth. - השתמשו ב-Node.js runtime לתמיכה מלאה ב-crypto.
- הגדירו כותרות (headers) בבקשה (request), לא בתגובה (response).
- תמיד אמתו את ה-JWT בתוך Server Components.