איך וואטסאפ שדרגה את תהליך הכניסה למיליארד משתמשים באמצעות מפתחות גישה, והפכה אותו למאובטח ופשוט יותר
משך הקריאה: 8 דקות
WhatsApp היא פלטפורמת ההודעות הגדולה בעולם, שמשרתת מיליארדי משתמשים ברחבי העולם. היא כלי התקשורת שמשמש כברירת מחדל אנשים באזורים שונים, ומחברת בין משתמשים באמצעות הודעות פרטיות, אמינות ומאובטחות.
"מה שהכי מרגש אותי זה ההיקף העצום של ההשפעה של וואטסאפ. "אפילו שיפור קטן בוואטסאפ משפיע על מיליארדי משתמשים ברחבי העולם", אומר מאיאנק מאנוג'ה, מהנדס Android בצוות הרישום והגישה של וואטסאפ, שהוביל את התכנון וההטמעה של האימות מבוסס מפתחות הגישה בוואטסאפ.
כדי לפתח מוצר לקהל בסדר גודל כזה, צריך להתמודד עם מגוון רחב של תנאי רשת, יכולות של מכשירים ורמות של אוריינות דיגיטלית. ב-WhatsApp זיהו את הפוטנציאל בשלב מוקדם, והתחייבו לאמץ את מפתחות הגישה ב-2023. כך היא הפכה לאחת מהאפליקציות הגדולות הראשונות למשתמשים ששילבו את הטכנולוגיה הזו. המטרה של וואטסאפ בהטמעת מפתחות הגישה הייתה לספק אפשרות מהירה ועמידה בפני פישינג, שמפחיתה באופן משמעותי את החיכוך של המשתמשים ומספקת הגנה חזקה מפני השתלטות על חשבונות וגניבת פרטי כניסה.
ההחלטה להשתמש במפתחות גישה
בוואטסאפ, חשוב להציע כמה שיטות גישה כדי שלמשתמשים יהיה קל יותר להישאר מחוברים ולקבל גישה מחדש כשצריך. מפתחות גישה מאפשרים למשתמשים להתחבר בקלות בלחיצה אחת, בלי סיכון לפישינג, ופועלים בצורה אמינה גם באזורים שבהם שליחת הודעות OTP לא תמיד עובדת.
מפתחות הגישה משתמשים בקריפטוגרפיה של מפתחות ציבוריים ופרטיים כדי להחליף את ההזנה הידנית באימות ביומטרי או בשיטה לפתיחת הנעילה. תהליך העבודה הזה משפר באופן משמעותי את מהירות הכניסה, כי הוא מצמצם את התהליך ללחיצה אחת דרך ממשק מאוחד של גיליון תחתון ששומר על רמת המעורבות של משתמשים בהקשר של האפליקציה. יש לכך שני יתרונות: מפתחות הגישה מספקים למשתמשים חוויית התחברות יעילה, ובמקביל מספקים הגנה מובנית חזקה מפני התקפות פישינג. חשוב לציין שהם פועלים באופן אמין גם באזורים שבהם שליחת OTP ב-SMS רגיל לא תמיד עובדת.
שיטות חזקות ומגוונות לגישה לחשבון מבטיחות שהמשתמשים אף פעם לא יאבדו את הגישה לדברים שהכי חשובים להם.
שילוב בצד הלקוח
מנקודת המבט של מפתחי וואטסאפ, Credential Manager API סיפק ממשק נקי ומאוחד שהסתיר את המורכבות של ספקי פרטי הכניסה הבסיסיים. אחרי שמיפינו את תהליכי השילוב הראשוניים, ממשק ה-API הפך לפשוט, והיצירה והאחזור של פרטי הכניסה התבצעו לפי דפוסי בקשה ותגובה מוגדרים היטב. מדריך ההטמעה זמין במאמרי העזרה למפתחים של Android.
הנתיב האופטימלי פעל מההתחלה, אבל כשמדובר בבסיס משתמשים מגוון עם יצרני ציוד מקורי שונים, כמה גרסאות של Android ותצורות מכשירים שונות (למשל, קוד אימות בלבד לעומת נתונים ביומטריים, או Android 13 לעומת Android 14 ואילך), נתקלנו במקרי קצה חסרי תקדים. הבעיות האלה כללו משתמשים ללא נעילת מסך, סוגי חריגים לא צפויים, גרסאות לא עדכניות של Play Services והתנהגות לא עקבית של ספק פרטי הכניסה.
כדי להתגבר על המכשולים האלה, הצוותים של וואטסאפ ו-Google שיתפו פעולה באופן הדוק והתמודדו עם כמה אתגרים:
- אופטימיזציה של תהליך החיפוש של פרטי הכניסה: תהליך החיפוש הראשוני הציג זמן אחזור ארוך, במיוחד למשתמשים שעדיין לא יצרו מפתח גישה. רוב משתמשי וואטסאפ נכללים בקבוצה הזו בשלבים המוקדמים, ולכן העיכוב הזה השפיע על כמעט כל כניסה לחשבון. באמצעות ניתוח נתיב הקריאה וזיהוי צווארי הבקבוק, וואטסאפ האיצה משמעותית את התהליך והשיגה שיפורים בביצועים שהועילו בסופו של דבר לכל הסביבה העסקית של Android.
- טיפול במצבים זמניים: וואטסאפ בנתה שכבה מקיפה לטיפול בשגיאות כדי להתמודד עם מכשולים ספציפיים למכשיר, כמו זמינות של מנהל הסיסמאות, נעילת מסך שלא הוגדרה, בעיות קישוריות לסירוגין, חומרה לא תואמת, גרסאות מיושנות של Play Services, סיווג חריגים למצבים שניתן לשחזר ולמצבים סופיים. כך אפשר היה להפחית את ההשפעה של התקלה (graceful degradation) – אם תהליך של מפתח גישה לא הושלם, המערכת חזרה באופן בטוח לאימות המסורתי בלי להשאיר את המשתמש במצב לא תקין.
- טיפול בחריגות ספציפיות למערכת ההפעלה: כשנתוני הטלמטריה חשפו מכשולים ספציפיים למכשיר, כמו GetPublicKeyCredentialDomException (פענוח פרטי הכניסה נכשל) במכשירי Android 13 מסוימים, ו-CreatePublicKeyCredentialDomException (לא ניתן לקבל חשבון סנכרון) במהלך יצירת מפתח גישה ב-Android 14, Google וצוות וואטסאפ חקרו את שורש הבעיה והטמיעו שיפורים ברמת הפלטפורמה כדי להבטיח תהליכי יצירה חלקים יותר. כאן אפשר למצוא מדריך מקיף לשגיאות, שכולל רשימה של קודי שגיאה נפוצים ותיאורים שקשורים ל-Credential Manager, ומידע על הסיבות לשגיאות.
| הערה: לקבלת הנחיות נוספות, כדאי לעיין בבלוג בנושא שיטות מומלצות למפתחות גישה כדי ללמוד איך לשפר את חוויית המשתמש כשמשתמשים במפתחות גישה. |
שיפור חוויית המשתמש
מכיוון שמפתחות הגישה היו קונספט חדש לגמרי בתחילת 2023, לא היו דפוסים מבוססים להצגת בקשה ליצירת מפתחות גישה. באמצעות בדיקות A/B נרחבות, הצוות של וואטסאפ פיתח מסגרת הקשרית שמטרגטת את המשתמשים שיפיקו את התועלת הרבה ביותר. האסטרטגיה הזו התפתחה כל הזמן: ככל שהתהליכים של Android OS הפכו לחוויה יעילה במסך אחד, וואטסאפ פישטה את ההנחיות שלה כדי למנוע ממשק משתמש מיותר או מבלבל.
ארכיטקטורה בצד השרת ומכשולים בפלטפורמות שונות
ב-backend, השרת של וואטסאפ מיישם את הטקסים הרגילים של WebAuthn/FIDO2. הקצה העורפי כתוב ב-Erlang וקורא לספריית Rust webauthn-rs דרך ממשק מקורי. ספריית Rust הזו מטפלת באימות החתימה ובניתוח פרטי הכניסה, וכך הקוד הפנימי יכול להישאר ממוקד בתזמור, באחסון ובכללי המוצר כמו זכאות, הגבלת קצב של יצירת בקשות ומחזור החיים של פרטי הכניסה.
ארכיטקטורת השרת מתזמרת את הטקסים העיקריים האלה באמצעות ארבע נקודות כניסה עיקריות, שמשולבות ברצפים של התחלה וסיום גם לרישום וגם לאימות:
1. רישום מפתח גישה
הרצף הזה מטפל בהנפקת אפשרויות יצירה ללקוח, באימות האישור לאחר שהלקוח מאשר את היצירה המוצלחת ובשמירה מאובטחת של פרטי הכניסה.
Erlang: התחלת הרישום
begin_registration(UserId) ->
Existing = list_credentials(UserId),
%% reuse the existing user handle, or mint a new one
{UserHandle, IsNew} = user_handle(Existing),
%% returns the client creation options and the server-side challenge state
#{client_safe := CreationOptions, server_only := ChallengeState} =
webauthn:start_registration(UserId, UserHandle, rp_config()),
%% excludeCredentials: the user's existing credential IDs, so the device won't re-enroll one
Options = with_exclude_credentials(CreationOptions, credential_ids(Existing)),
store_challenge(UserId, ChallengeState), %% short TTL
IsNew andalso reserve_user_handle(UserId, UserHandle),
Options.- זיהוי המשתמש: השרת בודק קודם אם יש פרטי כניסה קיימים כדי להשתמש שוב בכינוי משתמש קיים או ליצור כינוי חדש.
- יצירת אפשרויות ואתגר: מתבצעת קריאה לספריית WebAuthn כדי ליצור את אפשרויות היצירה ללקוח ומצב אתגר מאובטח לשרת.
- מניעת כפילויות: המאפיין הזה מחריג באופן מפורש את מזהי פרטי הכניסה הקיימים של המשתמש, כדי שהמכשיר לא ירשום בטעות מחדש מפתח גישה שכבר רשום.
- שמירת האתגר: השרת שומר זמנית את האתגר עם אורך חיים (TTL) קצר ושולח את האפשרויות בחזרה למכשיר הלקוח.
Erlang: Finish Registration
finish_registration(UserId, Attestation) ->
ChallengeState = get_challenge(UserId), %% must exist and be unexpired
#{credential_id := CredId, public_key := PubKey} =
webauthn:finish_registration(Attestation, ChallengeState, rp_config()),
ok = index_credential(CredId, UserId), %% map credential_id -> account
case multi_passkey_enabled(UserId) of
true -> add_credential(UserId, CredId, PubKey); %% append (oldest evicted past the cap)
false -> replace_credential(UserId, CredId, PubKey) %% single-passkey mode
end,
notify_client(UserId, {passkey_created, CredId}),
ok.- אחזור האתגר: השרת מאחזר את האתגר השמור, ומוודא שהוא עדיין קיים ושהתוקף שלו לא פג.
- אימות האישור: המערכת מעבירה את התגובה של הלקוח (האישור) ואת האתגר לספריית WebAuthn כדי לאמת את הבקשה ולחלץ את מזהה פרטי הכניסה החדש ואת המפתח הציבורי.
- הוספת פרטי הכניסה לאינדקס: מזהה פרטי הכניסה החדש ממופה ישירות לחשבון המשתמש כדי לאפשר חיפוש מהיר בהמשך.
- שמירה וניהול של מגבלות: אם התכונה "מספר מפתחות גישה" מופעלת, השרת יוסיף את פרטי הכניסה החדשים לרשימה של המשתמש (ויסיר את הפרטים הישנים ביותר אם המכסה תתמלא). אם התכונה לא מופעלת, השרת יחליף את פרטי הכניסה הקיימים במצב "מפתח גישה יחיד".
2. אימות פרטי כניסה
בדומה ליצירה, שרת האפליקציה מטפל בתהליך האימות על ידי תזמון רצף ההתחברות. זה כולל אימות של ההצהרה אחרי אימות מוצלח של הלקוח, ועדכון דינמי של פרטי הכניסה השמורים בכל פעם ש-WebAuthn מאותת שצריך לרענן.
Erlang: התחלת האימות
begin_authentication(UserId) ->
Credentials = list_valid_credentials(UserId),
#{client_safe := RequestOptions, server_only := ChallengeState} =
webauthn:start_authentication(Credentials, rp_config()),
store_challenge(UserId, ChallengeState), %% short TTL
RequestOptions.- אחזור פרטי כניסה תקינים: השרת מחפש את כל פרטי הכניסה התקינים שמשויכים למשתמש.
- יצירת אתגר: השרת משתמש בפרטי הכניסה האלה כדי ליצור אפשרויות בקשה ללקוח, ויוצר אתגר חדש בצד השרת.
- אחסון והחזרה: כמו בתהליך הרישום, האתגר נשמר באופן זמני, ואפשרויות הבקשה מועברות לאפליקציית הלקוח.
Erlang: Finish Authentication
finish_authentication(UserId, Assertion) ->
ChallengeState = get_challenge(UserId),
Credentials = list_valid_credentials(UserId),
case webauthn:finish_authentication(Credentials, Assertion, ChallengeState) of
#{user_verified := true, credential_id := CredId, needs_update := NeedsUpdate} = Result ->
%% webauthn tells us when the stored credential should be refreshed
NeedsUpdate andalso refresh_credential(UserId, CredId, Result),
mark_credential_used(UserId, CredId),
{ok, CredId};
_ ->
{error, not_allowed}
end.- אימות ההצהרה: השרת מאחזר את האתגר השמור ואת פרטי הכניסה התקינים, ואז מבקש מספריית WebAuthn לאמת את ההצהרה של הלקוח.
- רענון לפי הצורך: אם המשתמש אומת בהצלחה, השרת בודק את הדגל needs_update. ספריית WebAuthn משתמשת בדגל הזה כדי לאותת אם צריך לרענן בשרת את מצב פרטי הכניסה השמורים.
- סיום: השרת מסמן את פרטי הכניסה ככאלה שכבר השתמשו בהם ומשלים את תהליך ההתחברות.
מידע נוסף על רישום שרת זמין במדריך ההטמעה כאן.
שיקולים מתקדמים בנוגע לארכיטקטורה
הטמעת מפתחות גישה בשרת בקנה מידה נרחב הציבה אתגרים ייחודיים, במיוחד בכל הקשור לארכיטקטורת החשבון ולסנכרון המכשירים. אשיש צ'אודהארי (Ashish Choudhary) מצוות ה-backend של וואטסאפ הדגיש את המכשולים העיקריים שהם נתקלו בהם:
- מעבר לכמה מפתחות גישה לכל חשבון: לוגיקת השרת הקודמת של וואטסאפ הייתה קשורה באופן הדוק להנחה שיש פרטי כניסה יחידים לכל משתמש. כדי לתמוך במציאות של התאמה רחבה מודרנית, הם פיתחו מערכת רשימה מוגבלת שמסירה באופן חכם את פרטי הכניסה הישנים ביותר ברגע שמגיעים למגבלה. כדי להבטיח יציבות מוחלטת, השינוי המבני המשמעותי הזה הושק בהדרגה באמצעות ניסויים קפדניים.
- איזון מחזור החיים של פרטי הכניסה: ניהול התוקף של פרטי הכניסה דרש טיפול עדין. אם מבטלים את התוקף של פרטי הכניסה באופן אגרסיבי מדי, זה מאלץ את המשתמשים להירשם מחדש שלא לצורך. מצד שני, אם מקלים מדי, פרטי כניסה לא עדכניים מצטברים. כדי לפתור את הבעיה הזו, וואטסאפ הטמיעה מצבי מחזור חיים מאוזנים ששומרים על אבטחה הדוקה בלי לתסכל את המשתמשים, וגם ניקוי אוטומטי ברקע של מפתחות גישה לא פעילים.
חשיבה מחדש על סנכרון בין מכשירים
הארכיטקטורה החזקה הזו, שכוללת כמה מפתחות גישה, גם אפשרה לוואטסאפ לשנות לחלוטין את השימושיות בפלטפורמות שונות. התהליך הרגיל של WebAuthn בין מכשירים דורש סריקה של קוד QR במכשיר אחד ואימות באמצעות Bluetooth במכשיר אחר. עם זאת, בוואטסאפ גילו שהתלות ב-Bluetooth לא אמינה, ושהמשתמשים מתבלבלים לעיתים קרובות בין קודי ה-QR החדשים לבין התהליך הקיים של קישור לוואטסאפ ווב.
במקום לאלץ מנגנון העברה שברירי בין מכשירים, וואטסאפ מאפשרת למשתמשים להחזיק מפתחות גישה באופן מקורי בכמה סביבות, כמו מנהל הסיסמאות של Google ב-Android וצרור המפתחות של iCloud ב-iOS. כשמשתמשים עוברים לפלטפורמה חדשה, הם פשוט יוצרים מפתח גישה חדש בכניסה הבאה לחשבון. הגישה הזו לא דורשת שום מאמץ מצד המשתמש, והיא פועלת בצורה חלקה על גבי תשתית השרת החדשה של מפתחות הגישה המרובים.
מה צפוי לנו
מאז שהשיקה את מפתחות הגישה, וואטסאפ נהנתה מאימוץ אורגני נרחב בקרב בסיס המשתמשים העצום שלה. האפליקציה שיפרה באופן משמעותי את חוויית המשתמש על ידי הפיכת תהליך הכניסה המסורתי, שכולל כמה שלבים, לתנועה ביומטרית אחת ופשוטה. כדי להמשיך את המומנטום, וואטסאפ מרחיבה עכשיו את השימוש במפתחות גישה מעבר לכניסות הראשוניות, ובוחנת אימות מחדש חלק בתוך האפליקציה לפעולות רגישות בחשבון, כמו גיבויים מוצפנים באמצעות מפתחות גישה.
אנחנו בוואטסאפ פועלים באופן פעיל בשיתוף עם פלטפורמות שותפות כדי לפתח דרכים פשוטות יותר ליצירת פרטי כניסה, מתוך ציפייה שהחסמים לכניסה יצטמצמו באופן טבעי ככל שהיכולות הביומטריות של המכשירים יתרחבו.
המלצה למפתחים שיוצרים אפליקציות בקנה מידה נרחב
למפתחים שמתכוננים לשלב מפתחות גישה בקנה מידה נרחב, הצוות של וואטסאפ משתף את ההמלצות החשובות הבאות:
- השקיעו מוקדם בטקסונומיה של שגיאות: סווגו את המגוון הרחב של החריגות ב-Credential Manager למצבים שניתן לשחזר לעומת מצבים סופיים, והגדירו נתיבי חלופות ברורים ונוחים לכל תרחיש.
- הבנת משפך הזכאות: כדאי להגדיר בדיקות של יכולות המכשיר, כמו נוכחות של נעילת מסך, חומרה ביומטרית וגרסאות של Google Play Services, ולתכנן תהליכים שיחריגו באופן יזום משתמשים לא כשירים, במקום שהתהליך ייכשל באמצע.
- הכינו את האפליקציה למצב חלופי: השתמשו במפתחות גישה כשיטת אימות ראשית אופטימלית למכשירים תואמים, אבל תמיד שמרו על השיטות המסורתיות כגיבוי אוניברסלי אמין.
- תכנון לפרגמנטציה של גרסאות מערכת ההפעלה: ההתנהגות של מפתחות הגישה עשויה להשתנות בין מערכות הפעלה שונות. חשוב לבדוק את התכונה ביסודיות ב-Android בגרסאות 13, 14 ו-15 ואילך, ולהביא בחשבון את ההבדלים בין ממשקי המשתמש לבחירת פרטי כניסה של יצרני ציוד מקורי (OEM) שונים.
- הסבירו על מפתחות הגישה והציעו אותם בהקשר המתאים: הציגו את האפשרות ליצור מפתח גישה באופן טבעי במהלך פעולות שקשורות לאבטחה. כדי לעודד את המשתמשים להשתמש בתכונה, חשוב להדגיש בבירור את הצעת הערך (מהירות ואבטחה) בשפה נגישה.
- מעקב יזום: הסביבה משתנה עם כל עדכון של מערכת ההפעלה. עוקבים באופן קבוע אחרי דפוסי השגיאות והזמן שלוקח לטעון את המודעות כדי להתכונן לשינויים בסביבת המכשירים.
איך מתחילים להשתמש במפתחות גישה וב-Credential Manager
כדי להתנסות במפתחות גישה וב-Credential Manager ב-Android, אפשר להיעזר במדריך ההטמעה ובקוד לדוגמה שזמין לכולם.
אם יש לכם שאלות או בעיות, אתם יכולים לשתף אותן איתנו דרך מעקב הבעיות של Android Credentials.
-
מקרים לדוגמהחברת Uber השתמשה ב-Android Restore Credentials API כדי לייעל את הכניסה למכשירים חדשים, וצפויה לצמצם 4 מיליון כניסות ידניות בשנה וכך לשפר את שימור המשתמשים.
Niharika Arora, Tracy Agyemang • משך הקריאה: 5 דקות -
מקרים לדוגמהמבזקי חדשות, בידור, ספורט ופוליטיקה – X היא אפליקציה של רשת חברתית שנועדה לעזור לכמעט 500 מיליון משתמשים ברחבי העולם לקבל את הסיפור המלא עם כל התגובות בשידור חי.
Niharika Arora, Tracy Agyemang • משך הקריאה: 3 דקות -
מקרים לדוגמה Grab מפחיתה את שגיאות ה-ANR ב-32% ומשפרת את זמן ההפעלה ב-35% באמצעות R8 ואופטימיזציה מבוססת-פרופיל
Grab היא אפליקציית-העל המובילה בדרום-מזרח אסיה, שמציעה משלוחים, ניידות ושירותים פיננסיים למיליוני משתמשים בשמונה מדינות באמצעות אפליקציה אחת.
Ajesh Pai, Nguyen Van Minh, Tracy Agyemang • משך הקריאה: 5 דקות
רוצים לקבל טיפים עדכניים לפיתוח Android ישירות לאימייל כל שבוע?