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

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

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

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

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

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

איך המידע על השימוש והאימות מאומת בשרת

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

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

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

ציון הפרמטר userVerification

בהתאם למפרט WebAuthn, ספק השירות יכול לבקש אימות משתמש באמצעות פרמטר userVerification גם ביצירת אישורים וגם בהצהרה. הוא מקבל את הערכים 'preferred', ‏ 'required' או 'discouraged', שפירושם בהתאמה:

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

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

מתי כדאי להשתמש בuserVerification='required'

כדאי להשתמש ב-userVerification='required' אם אתם חושבים שגם UP וגם UV נחוצים לחלוטין.

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

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

סיכום

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