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

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

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

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

צילום מסך של תיבת דו-שיח לאימות משתמש ב-iCloud Keychain ב-macOS. בתיבת הדו-שיח, המשתמש מתבקש להיכנס באמצעות Touch ID. בנוסף, מוצג המקור שמבקש אימות ושם המשתמש. בפינה השמאלית העליונה של תיבת הדו-שיח מופיע הלחצן 'ביטול'.
תיבת דו-שיח לאימות משתמש ב-iCloud Keychain ב-macOS.
צילום מסך של תיבת דו-שיח לאימות משתמש ב-Chrome ל-Android. בתיבת הדו-שיח, המשתמש מתבקש לאמת את זהותו באמצעות זיהוי פנים או זיהוי טביעת אצבע, ומוצג המקור שמבקש לבצע אימות. בפינה הימנית התחתונה מופיעה אפשרות לאימות באמצעות מספר PIN.
תיבת הדו-שיח לאימות משתמשים ב-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, ואם הדגל UV הוא true או false, בהתאם לדרישה.

ציון הפרמטר userVerification

בהתאם למפרט של WebAuthn, ה-RP יכול לבקש אימות משתמש באמצעות פרמטר userVerification גם ביצירת פרטי הכניסה וגם בטענת הנכוֹנוּת (assertion). אפשר להזין בו את הערכים '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 לא זמין, המשתמש מתבקש ללחוץ על לחצן כדי לדלג על אימות המשתמש, והפרטים של מפתח הציבור כוללים את הדגל UV‏ false.

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

מתי להשתמש ב-userVerification='required'

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

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

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

סיכום

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