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

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

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

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

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

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

איך מאמתים את UP ו-UV בשרת

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

תיאור של מבנה נתוני האימות.
שדות של נתוני מאמת בפרטי כניסה של מפתח ציבורי. משמאל לימין, כל מקטע במבנה הנתונים קורא 'RP ID HASH' (32 בתים), 'FLAGS' (בית אחד), 'COUNTER' (4 בתים, big-endian uint32), '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 לאימות משתמש באמצעות מפתח גישה.