spinny:~/writing $ vim passkeys-webauthn-passwordless-authentication.md
1~2סיסמאות הן אחד מהדברים האלה שנורמלנו רק בגלל שחיינו איתן במשך שנים. משתמשים שוכחים אותם, עושים בהם שימוש חוזר, כותבים אותם היכן שהם לא צריכים. על הצוותים לנהל איפוסים, מדיניות, גיבוב, הדלפות, פישינג ותמיכה.3~4ה-passkey לא הופכים את האימות למושלם, אבל הם מסירים בעיה ענקית: השרת כבר לא צריך לשמור סוד משותף עם המשתמש.5~6## מה באמת קורה7~8passkey הוא אישור המבוסס על WebAuthn. כאשר המשתמש יוצר אותו, המכשיר יוצר זוג מפתחות:9~10- מפתח פרטי, שנשאר במכשיר או במנהל הסיסמאות;11- מפתח ציבורי, שהשרת יכול לשמור.12~13בכניסה לשרת לא שואלים "תגיד לי את הסיסמה". שלח אתגר אקראי. המכשיר חותם עליו עם המפתח הפרטי. השרת מאמת את החתימה באמצעות המפתח הציבורי.14~15זה החלק הנחמד: אם מסד הנתונים נגנב, אין בפנים סיסמאות לפצח. ואם משתמש מגיע לדומיין מזויף, ה-passkey אינו תקף עבור אותו דומיין. זו לא רק נוחות, זו הגנה קונקרטית מפני פישינג.16~17## הדפדפן פועל כגשר18~19בדפדפן שני API העיקריים הם:20~21- `navigator.credentials.create()` כדי ליצור passkey;22- `navigator.credentials.get()` כדי להשתמש בו במהלך הכניסה.23~24אבל ההיגיון החשוב הוא בשרת. השרת חייב ליצור את האתגר, לשמור אותו באופן זמני, לאמת את התגובה, לבדוק את המקור ואת Relying Party ID, ואז ליצור את ההפעלה.25~26חלק הלקוח צריך להיות כמעט משעמם:27~28```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());30~31const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});34~35await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```41~42אם אתה מוצא את עצמך מיישם הצפנה WebAuthn ביד, הפסק. השתמש בספרייה חזקה בצד השרת. השגיאות כאן אינן "באגים חמודים", אלא חורי אימות.43~44## מה לשמור במסד הנתונים45~46אין צורך להציל חצי עולם. בדרך כלל מספיק:47~48- מזהה של האישור;49- מפתח ציבורי;50- משתמש מחובר;51- כל מונה אימות או מטא נתונים;52- הובלות, אם שימושי עבור UX;53- שם שנבחר על ידי המשתמש;54- תאריך יצירה ושימוש אחרון.55~56טבלה מינימלית עשויה להיראות כך:57~58```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```69~70אז הייתי מוסיף יומני ביקורת והתראות: אם מישהו יוצר passkey חדש בחשבון שלי, אני רוצה לדעת על זה.71~72## UX חשוב יותר מהדגמה73~74ההדגמה של passkey תמיד יפה: אתה לוחץ, Face ID, אתה בפנים. המוצר בפועל מסובך יותר.75~76מישהו מחליף את הטלפון שלו. מישהו משתמש במחשב חברה נעול. יש אנשים שלא מבינים מדוע הדפדפן מציע passkey. מישהו מאבד גישה למכשיר שלו.77~78זו הסיבה שלא הייתי מתחיל ב"מהיום אין יותר סיסמאות לכולם". הייתי מתחיל ככה:79~801. passkey אופציונלי עבור משתמשים פנימיים;812. הצעה ליצור אחד לאחר כניסה מוצלחת;823. דף חשבון לשינוי שם ולהסרה של passkey;834. סתירה ברורה;845. השקה הדרגתית בכניסה הראשית.85~86הטקסט בממשק צריך להיות פשוט. "השתמש במסך הנעילה של המכשיר שלך" עדיף על "אימות עם אישור תושב FIDO2".87~88## טעויות שהייתי נמנע מהם89~90אל תייצר אתגרים על הלקוח. האתגר נוצר בשרת ויש לאמת אותו פעם אחת בלבד.91~92אל תסמוך רק על מזהה האישור. עליך לאמת חתימה, אתגר, מקור וRelying Party ID.93~94אל תמחק תקלות לפני שיש לך זרימת התאוששות טובה. חסר סיסמה לא חייב להפוך ל"אם אתה מאבד את הטלפון שלך אתה בחוץ לנצח".95~96אל תתייחס ל-passkey כאל כפתור חזיתי בלבד. הסתרת כפתור אינה אבטחה: האימות האמיתי הוא בצד השרת.97~98## Passkey-ראשון או passkey ידידותי?99~100עבור מוצר חדש אתה יכול לחשוב passkey-קודם כל. עבור אפליקציה קיימת אני מעדיף passkey ידידותית: הוסף את passkey כשיטה מומלצת, מדוד הצלחה ובעיות, ואז הפחית בשלווה את משקל הסיסמה.101~102ההגירה האידיאלית אינה מורגשת. המשתמש מגלה שהכניסה קלה יותר, לא שהחברה שינתה את פרוטוקול האימות שלה.103~104## מסקנה105~106ה-passkey מעניינים מכיוון שהם משפרים את האבטחה ואת ה-UX בו זמנית, וזה נדיר. הם אינם שרביט קסמים: שחזור, תאימות, תמיכה והפצה נותרו מתוכננים היטב.107~108אבל השינוי הבסיסי הוא חזק. הפסיקו לבקש ממשתמשים להמציא סודות ולהגן עליהם. אתה נותן למכשיר לחתום על הוכחה קריפטוגרפית הקשורה לדומיין שלך. פחות זיכרון אנושי, פחות דיוג, פחות איפוסי סיסמה. הייתי אומר ששווה לקחת אותם ברצינות.109~110## מקורות111~112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116~
NORMAL · passkeys-webauthn-passwordless-authentication.md [readonly]116 lines · :q to close