ניתוח מעמיק של אימות משתמשים

במסמך הזה מוסבר על userVerification ב-WebAuthn ועל התנהגויות הדפדפן שנובעות מציון userVerification במהלך יצירה או אימות של מפתח גישה.

מהו 'אימות משתמש' ב-WebAuthn?

מפתחות הגישה מבוססים על קריפטוגרפיה של מפתח ציבורי. כשיוצרים מפתח גישה, נוצר זוג מפתחות ציבורי-פרטי, המפתח הפרטי מאוחסן אצל הספק של מפתח הגישה והמפתח הציבורי מוחזר לשרת ה-RP של הצד הנסמך. השרת יכול לאמת משתמש על ידי אימות חתימה שחתומה על ידי אותו מפתח גישה, באמצעות המפתח הציבורי המותאם. השדה 'משתמש נוכחי' הסימון (UP) בפרטי הכניסה של מפתח ציבורי מוכיח שמישהו ביצע אינטראקציה עם המכשיר במהלך האימות.

אימות משתמש הוא שכבת אבטחה אופציונלית שמטרתה לטעון שהאדם הנכון היה נוכח במהלך האימות, ולא רק אדם מסוים, כפי שמצהירה נוכחות המשתמש. בסמארטפונים, כדי לעשות את זה, בדרך כלל משתמשים במנגנון נעילת המסך – מידע ביומטרי או קוד אימות או סיסמה. אם בוצע אימות משתמש מדווח במסגרת 'UV' שמוחזר בנתוני המאמת במהלך הרישום והאימות של מפתח הגישה

צילום מסך של תיבת הדו-שיח לאימות משתמש ב'צרור המפתחות של iCloud' ב-macOS. בתיבת הדו-שיח תוצג למשתמש בקשה להיכנס לחשבון באמצעות Touch ID, והמקור שמבקש אימות יוצג, וגם שם המשתמש. בפינה השמאלית העליונה של תיבת הדו-שיח מופיע לחצן עם התווית 'ביטול'.
תיבת דו-שיח לאימות משתמש ב-iCloud Keychain ב-macOS.
צילום מסך של תיבת דו-שיח לאימות משתמש ב-Chrome ל-Android. בתיבת הדו-שיח תוצג למשתמשים בקשה לאמת את הזהות שלהם באמצעות זיהוי פנים או טביעת אצבע, ותציג את המקור שממנו נשלחה הבקשה לאימות. בפינה הימנית התחתונה יש אפשרות לאימות באמצעות קוד אימות.
תיבת דו-שיח לאימות המשתמש ב-Android Chrome.

איך מתבצע אימות של UP ו-UV בשרת

הדגלים הבוליאניים של נוכחות המשתמש (UP) ואימות המשתמש (UV) מאותרים לשרת בשדה הנתונים של מאמת החשבונות. במהלך האימות, אפשר לאמת את התוכן של שדה הנתונים של מאמת החשבונות על ידי אימות החתימה באמצעות המפתח הציבורי שמאוחסן. כל עוד החתימה חוקית, השרת יכול להתייחס בדגלים אמיתיים.

תמונה של מבנה נתוני האימות. משמאל לימין, בכל קטע במבנה הנתונים מופיע הכיתוב 'RP ID HASH' (32 בייטים), 'FLAGS' (בייט אחד), 'COUNTER' (4 בייטים, big-endian uint32), 'ATTESTE CRED. נתונים (אורך משתנה אם קיים), ו-תוספים (אורך משתנה אם קיים (CBOR)). 'דגלים' הקטע הורחב ומציג רשימה של דגלים אפשריים, משמאל לימין: 'ED', 'AT', '0', 'BS', 'BE', 'UV', '0' ו-'UP'.
שדות נתונים ממאמת החשבונות בפרטי הכניסה של מפתח ציבורי.

במהלך הרישום והאימות של מפתח הגישה, השרת צריך לבדוק שהסימון UP הוא true, ואם דגל UV הוא true או false, בהתאם לדרישה.

ציון הפרמטר userVerification

לפי מפרט WebAuthn, ה-RP יכול לבקש אימות משתמש באמצעות הפרמטר userVerification גם ביצירת פרטי כניסה וגם בטענת נכונות (assertions). הפונקציה מקבלת את הערך 'preferred', 'required' או 'discouraged', בהתאמה:

  • 'preferred' (ברירת המחדל): עדיף להשתמש בשיטת אימות משתמש במכשיר, אבל אפשר לדלג עליה אם היא לא זמינה. פרטי הכניסה לתגובה מכילים ערך של דגל UV: true אם בוצע אימות משתמש ו-false אם לא בוצע UV.
  • 'required': נדרשת הפעלה של שיטת אימות משתמש שזמינה במכשיר. אם אין מזהה זמין, הבקשה תיכשל באופן מקומי. כלומר, פרטי הכניסה לתשובה תמיד מוחזרים כשסימון קרינת ה-UV מוגדר ל-true.
  • 'discouraged': לא מומלץ להשתמש בשיטת אימות של משתמשים. עם זאת, בהתאם למכשיר, ייתכן שיתבצע אימות משתמש בכל מקרה, ודגל קרינת UV יכול להכיל true או false.

קוד לדוגמה ליצירת מפתח גישה:

const publicKeyCredentialCreationOptions = {
  // ...
  authenticatorSelection: {
    authenticatorAttachment: 'platform',
    residentKey: 'required',
    requireResidentKey: true,
    userVerification: 'preferred'
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

קוד לדוגמה לאימות באמצעות מפתח גישה:

const publicKeyCredentialRequestOptions = {
  challenge: /* Omitted challenge data... */,
  rpId: 'example.com',
  userVerification: 'preferred'
};

const credential = await navigator.credentials.get({
  publicKey: publicKeyCredentialRequestOptions
});

איזו אפשרות כדאי לך לבחור עבור userVerification?

הערך של userVerification שבו צריך להשתמש תלוי בדרישות האפליקציה ובצרכים של חוויית המשתמש.

מתי להשתמש במאפיין userVerification='preferred'

שימוש בuserVerification='preferred' אם חוויית המשתמש חשובה לך יותר מההגנה.

יש סביבות שבהן אימות המשתמשים מורכב יותר מהגנה. לדוגמה, ב-macOS, ש-Touch ID לא זמין (כי המכשיר לא תומך בו, הוא מושבת או שהמכשיר נמצא במצב מיש), המשתמש מתבקש להזין את סיסמת המערכת שלו במקום זאת. הדבר גורם לקשיים והמשתמשים עלולים לנטוש לגמרי את האימות. אם ביטול החיכוך חשוב לכם יותר, כדאי להשתמש ב-userVerification='preferred'.

צילום מסך של תיבת הדו-שיח של מפתח הגישה ב-macOS, שמופיעה כש-Touch ID לא זמין. תיבת הדו-שיח תכיל מידע כמו המקור שמבקש אימות, וגם שם המשתמש. בפינה השמאלית העליונה של תיבת הדו-שיח מופיע לחצן עם התווית 'ביטול'.
תיבת דו-שיח של מפתח גישה מוצגת ב-macOS כש-Touch ID לא זמין.

עם הערך userVerification='preferred', דגל קרינת ה-UV הוא true אם אימות המשתמש בוצע בהצלחה, ו-false אם מדלגים על אימות המשתמש. לדוגמה, ב-macOS שבהן Touch ID לא זמין, המשתמש מתבקש ללחוץ על לחצן כדי לדלג על אימות המשתמש, ופרטי הכניסה של המפתח הציבורי כוללים דגל UV false.

דגל קרינת ה-UV יכול להיות אות בניתוח הסיכונים. אם ניסיון הכניסה נראה מסוכן בגלל גורמים אחרים, כדאי להציג למשתמש אימותים נוספים בכניסה לחשבון אם לא בוצע אימות.

מתי להשתמש במאפיין userVerification='required'

מומלץ להשתמש ב-userVerification='required' אם לדעתכם גם UP וגם UV הם הכרחיים.

החיסרון של האפשרות הזו הוא מצב של קשיים נוספים בזמן הכניסה לחשבון. לדוגמה, ב-macOS שבהן Touch ID לא זמין, המשתמש התבקש להזין את סיסמת המערכת שלו.

באמצעות userVerification='required', אפשר לוודא שאימות המשתמש מתבצע במכשיר. יש לוודא שהשרת מאמת שסימון קרינת ה-UV הוא true.

סיכום

מינוף של אימות המשתמשים מאפשר לגורמים שנעזרים במפתחות גישה כדי להעריך את הסבירות שבעל המכשיר ייכנס לחשבון. הם בוחרים אם לדרוש אימות של המשתמש או להפוך אותו לאופציונלי, בהתאם למידת ההשפעה הקריטית של מנגנון הכניסה החלופי על תהליך הכניסה של המשתמש. מוודאים שהשרת בודק את הסימון UP ודגל UV כדי לאמת משתמש עם מפתח גישה.