פרטי כניסה של FIDO, כמו מפתחות גישה, נועדו להחליף את הסיסמאות, אבל רובם גם מאפשרים למשתמשים להיכנס בלי להקליד שם משתמש. כך המשתמשים יכולים לבצע אימות על ידי בחירת חשבון מרשימת מפתחות הגישה שיש להם לאתר הנוכחי.
גרסאות קודמות של מפתחות אבטחה תוכננו כשיטות אימות דו-שלבי, והיה צריך להזין את המזהים של פרטי הכניסה הפוטנציאליים, כלומר להזין שם משתמש. פרטי כניסה שמפתח אבטחה יכול למצוא בלי לדעת את המזהים שלהם נקראים פרטי כניסה שניתנים לגילוי. רוב פרטי הכניסה של FIDO שנוצרים היום הם פרטי כניסה שניתנים לגילוי, במיוחד מפתחות גישה שמאוחסנים במנהל סיסמאות או במפתח אבטחה מודרני.
כדי לוודא שפרטי הכניסה נוצרים כמפתחות גישה (פרטי כניסה שניתן לגלות), צריך לציין את residentKey ו-requireResidentKey כשיוצרים את פרטי הכניסה.
צדדים נסמכים (RP) יכולים להשתמש בפרטי כניסה שניתנים לגילוי על ידי השמטת allowCredentials במהלך האימות של מפתח הגישה. במקרים כאלה, הדפדפן או המערכת מציגים למשתמש רשימה של מפתחות גישה זמינים, שמזוהים לפי המאפיין user.name שהוגדר בזמן היצירה. אם המשתמש בוחר באחת מהן, הערך של user.id ייכלל בחתימה שתתקבל. לאחר מכן, השרת יכול להשתמש בפרטים האלה או במזהה פרטי הכניסה שהוחזר כדי לחפש את החשבון במקום שם משתמש שהוקלד.
בממשקי משתמש לבחירת חשבון, כמו אלה שדיברנו עליהם קודם, אף פעם לא מוצגים פרטי כניסה שלא ניתנים לגילוי.
requireResidentKey וגם residentKey
כדי ליצור מפתח גישה, צריך לציין את authenticatorSelection.residentKey ואת authenticatorSelection.requireResidentKey ב-navigator.credentials.create() עם הערכים הבאים.
async function register () {
// ...
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
residentKey:
'required': צריך ליצור פרטי כניסה שניתן לגלות. אם אי אפשר ליצור את האובייקט, מוחזר הערךNotSupportedError.-
'preferred': הצד המסתמך מעדיף ליצור פרטי כניסה שניתן לגלות, אבל מקבל פרטי כניסה שלא ניתן לגלות. 'discouraged': הגורם המסתמך מעדיף ליצור פרטי כניסה שלא ניתנים לגילוי, אבל מקבל פרטי כניסה שניתנים לגילוי.
requireResidentKey:
- המאפיין הזה נשמר לצורך תאימות לדורות קודמים מ-WebAuthn Level 1, גרסה ישנה יותר של המפרט. צריך להגדיר את הערך
trueאם הערך שלresidentKeyהוא'required', אחרת צריך להגדיר את הערךfalse.
allowCredentials
גורמים מסתמכים יכולים להשתמש ב-allowCredentials ב-navigator.credentials.get() כדי לשלוט בחוויית האימות באמצעות מפתח הגישה. בדרך כלל יש שלושה סוגים של חוויות אימות באמצעות מפתחות גישה:
הצגת בורר חשבונות מודאלי
באמצעות פרטי כניסה שניתן לגלות, גורמים מסתמכים יכולים להציג חלון מודאלי לבחירת חשבון, שבו המשתמש יכול לבחור חשבון כדי להיכנס אליו, ולאחר מכן לבצע אימות משתמש. האפשרות הזו מתאימה לתהליך אימות באמצעות מפתח גישה שמתחיל בלחיצה על כפתור ייעודי לאימות באמצעות מפתח גישה.
כדי להשיג את חוויית המשתמש הזו, צריך להשמיט את הפרמטר allowCredentials ב-navigator.credentials.get() או להעביר אליו מערך ריק.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
הצגת מילוי אוטומטי של טופס מפתח גישה
המודל של בורר החשבונות שמתואר למעלה פועל היטב אם רוב המשתמשים משתמשים במפתחות גישה והם זמינים במכשיר המקומי. למשתמש שאין לו מפתחות גישה מקומיים, תיבת הדו-שיח המודאלית עדיין תופיע ותציע למשתמש להציג מפתח גישה ממכשיר אחר. בזמן שאתם מעבירים את המשתמשים למפתחות גישה, יכול להיות שתרצו להימנע מהצגת ממשק המשתמש הזה למשתמשים שלא הגדירו מפתח גישה.
במקום זאת, הבחירה במפתח גישה עשויה להיות משולבת בהנחיות למילוי אוטומטי של השדות בטופס כניסה רגיל, לצד שמות משתמשים וסיסמאות שנשמרו. כך, משתמש עם מפתחות גישה יכול "למלא" את טופס הכניסה על ידי בחירת מפתח הגישה שלו, משתמשים עם צמדי שם משתמש/סיסמה שמורים יכולים לבחור אותם, ומשתמשים שאין להם אף אחד מהם עדיין יכולים להקליד את שם המשתמש והסיסמה שלהם.
חוויית המשתמש הזו אידיאלית כשה-RP נמצא בתהליך העברה עם שימוש משולב בסיסמאות ובמפתחות גישה.
כדי להשיג את חוויית השימוש הזו, בנוסף להעברת מערך ריק למאפיין allowCredentials או השמטת הפרמטר, צריך לציין את mediation: 'conditional' ב-navigator.credentials.get() ולהוסיף אנוטציה לשדה להזנת קלט username ב-HTML עם autocomplete="username webauthn" או לשדה להזנת קלט password עם autocomplete="password webauthn".
הקריאה ל-navigator.credentials.get() לא תגרום להצגת ממשק משתמש, אבל אם המשתמש יתמקד בשדה להזנת קלט עם ההערות, כל מפתחות הגישה הזמינים ייכללו באפשרויות המילוי האוטומטי. אם המשתמש בוחר באחת מהן, הוא יעבור את האימות הרגיל של ביטול נעילת המכשיר, ורק אז ההבטחה שמוחזרת על ידי .get() תתבצע עם תוצאה. אם המשתמש לא בוחר מפתח גישה, ההבטחה לא מתממשת.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const cred = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
<input type="text" name="username" autocomplete=&qu>ot;username webauthn" ...
במאמר כניסה באמצעות מפתח גישה דרך מילוי אוטומטי של טפסים מוסבר איך ליצור את חוויית המשתמש הזו, וגם ב-Codelab הטמעת מפתחות גישה עם מילוי אוטומטי של טפסים באפליקציית אינטרנט.
אימות מחדש
במקרים מסוימים, כמו כשמשתמשים במפתחות גישה לאימות מחדש, המזהה של המשתמש כבר ידוע. במקרה כזה, אנחנו רוצים להשתמש במפתח גישה בלי שהדפדפן או מערכת ההפעלה יציגו בורר חשבונות. כדי לעשות את זה, צריך להעביר רשימה של מזהי פרטי כניסה בפרמטר allowCredentials.
במקרה כזה, אם אחד מפרטי הכניסה שצוינו זמין באופן מקומי, המשתמש מתבקש לבטל את נעילת המכשיר באופן מיידי. אם לא, המשתמש מתבקש להציג מכשיר אחר (טלפון או מפתח אבטחה) שכולל פרטי כניסה תקפים.
כדי להשיג את חוויית המשתמש הזו, צריך לספק רשימה של מזהי פרטי כניסה למשתמש שנכנס לחשבון. ה-RP אמור להיות מסוגל לשלוח שאילתה לגביהם כי המשתמש כבר מוכר. צריך לספק מזהי פרטי כניסה כאובייקטים מסוג PublicKeyCredentialDescriptor במאפיין allowCredentials ב-navigator.credentials.get().
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// Provide a list of PublicKeyCredentialDescriptors:
allowCredentials: [{
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, {
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, ...]
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
אובייקט PublicKeyCredentialDescriptor מורכב מהרכיבים הבאים:
-
id: מזהה של פרטי הכניסה של המפתח הציבורי שה-RP קיבל ברישום מפתח הגישה. -
type: השדה הזה הוא בדרך כלל'public-key'. transports: רמז לגבי סוגי התקשורת שנתמכים במכשיר שבו מאוחסן פרט הכניסה הזה. דפדפנים משתמשים ברמז הזה כדי לבצע אופטימיזציה של ממשק המשתמש שמבקש מהמשתמש להציג מכשיר חיצוני. אם הרשימה הזו קיימת, היא צריכה להכיל את התוצאה של הקריאה ל-getTransports()במהלך הרישום של כל פרטי כניסה.
סיכום
פרטי כניסה שניתנים לגילוי מאפשרים למשתמשים לדלג על הזנת שם המשתמש, וכך הופכים את חוויית הכניסה באמצעות מפתח גישה להרבה יותר ידידותית למשתמש. בעזרת השילוב של residentKey, requireResidentKey ו-allowCredentials, אתרי RP יכולים לספק חוויות כניסה:
- הצגת בורר חשבונות מודאלי.
- הצגת מילוי אוטומטי של טופס מפתח גישה.
- אימות מחדש.
השתמשו בפרטי כניסה שניתן לגלות בחוכמה. כך תוכלו לעצב חוויות כניסה מתוחכמות באמצעות מפתחות גישה, שהמשתמשים ימצאו בהן ערך וסביר יותר שישתמשו בהן.