אבטחה · 3 דקות קריאה ·
מה יש בתוך JWT, ולמה פענוח הוא לא אימות
טוקן JWT נראה כמו רצף תווים אקראי, אבל כל אחד יכול לקרוא אותו. מה יש בשלושת החלקים שלו, ומה הטעות שמובילה לפרצות אבטחה.

JWT (JSON Web Token) הוא המחרוזת הארוכה שמשאירה אתכם מחוברים להרבה אפליקציות ו-API. הוא נראה מוצפן, אבל ברוב המקרים הוא לא: כל מי שמחזיק בטוקן יכול לקרוא מה יש בו.
שלושה חלקים, מופרדים בנקודות
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiJ9.3q2-7w…
└ header ──────────┘ └ payload ───────┘ └ signature
ה-header אומר איך הטוקן חתום, למשל HS256 או RS256. ה-payload מכיל את ה-claims: מי המשתמש (sub), מתי הטוקן הונפק (iat) ומתי הוא פג (exp), ועוד כל מה שהאפליקציה מוסיפה, כמו הרשאות. שניהם פשוט JSON בקידוד base64url, וזה קידוד, לא הצפנה.
החתימה היא מה שחשוב
החלק השלישי הוא חתימה על שני הראשונים, שנוצרת עם סוד או מפתח פרטי. רק שרת שמחזיק במפתח הנכון יכול לבדוק אותה. אם מישהו משנה אפילו תו אחד ב-payload, למשל את התפקיד מ-user ל-admin, החתימה כבר לא מתאימה.
פענוח הוא לא אימות
טוקן שמתפענח יפה מספר לכם מה הוא טוען, לא אם הטענות נכונות. השרת שלכם חייב לאמת את החתימה עם המפתח, לדחות טוקנים שה-exp שלהם עבר ולקבל רק את האלגוריתמים שהוא מצפה להם, אף פעם לא "none". ספריות JWT עושות את זה בשבילכם; לדלג על זה זו פרצה קלאסית.
כללים מעשיים
אל תכניסו סודות כמו סיסמאות ל-payload, כי הוא קריא. שמרו על זמני תפוגה קצרים. התייחסו לטוקן כמו לסיסמה כל עוד הוא בתוקף: כל מי שמעתיק אותו יכול להשתמש בו עד שהוא פג.
איפה לשמור טוקן בדפדפן
כל סקריפט בדף יכול לקרוא את מה שנשמר ב-localStorage, כך שבאג XSS (הזרקת סקריפט) אחד מספיק כדי להדליף את הטוקן. עוגייה מסוג HttpOnly לא נגישה ל-JavaScript בכלל, וזה מסיר את הסיכון הזה; שלבו אותה עם הדגלים Secure ו-SameSite ועם הגנה מפני זיוף בקשות בין אתרים (CSRF). אין פתרון מושלם, אבל לטוקנים של סשן עוגיות HttpOnly הן ברירת המחדל הבטוחה יותר.
תפוגה וטוקני רענון
אי אפשר "לנתק" JWT בעצמו: הוא נשאר תקף עד זמן ה-exp שלו, אלא אם השרת מחזיק רשימת ביטולים. לכן טוקני גישה חיים בדרך כלל דקות ולא ימים. טוקן רענון ארוך יותר, שנשמר בזהירות רבה יותר ונבדק מול השרת, משמש לקבלת טוקן גישה חדש כשהישן פג.
השדות הנפוצים במבט אחד
iss מנפיק מי יצר את הטוקן
sub נושא המשתמש או הלקוח שהטוקן מתייחס אליו
aud קהל יעד איזה שירות צריך לקבל אותו
exp תפוגה זמן Unix שאחריו הוא לא תקף
nbf לא לפני זמן Unix שלפניו הוא לא תקף
iat זמן הנפקה זמן Unix שבו הוא נוצר
שדות הזמן הם חותמות זמן Unix בשניות. השרת חייב לבדוק גם את aud ולא רק את exp: טוקן תקף שהונפק לשירות אחד לא אמור להתקבל בשירות אחר.
קוראים טוקן
מפענח ה-JWT של 4Dev מפרק טוקן לחלקים ומציג את ה-header וה-payload כ-JSON קריא. הוא רק מפענח ולא בודק את החתימה. הטוקן נשלח לשרת של 4Dev לפענוח ולא נרשם ולא נשמר, ובכל זאת עדיף לא להדביק טוקנים חיים מסביבת ייצור, ולבטל כל טוקן שאתם חושדים שנחשף.