העדכונים האחרונים ב-API לניהול פרטי הכניסה

חלק מהעדכונים שמתוארים כאן מוסברים בסשן של Google I/O, כניסה מאובטחת וחלקה: שמירה על מעורבות המשתמשים:

Chrome 57

בגרסה 57 של Chrome נוסף השינוי החשוב הזה ל-Credential Management API.

אפשר לשתף פרטי כניסה מתת-דומיין אחר

עכשיו Chrome יכול לאחזר פרטי כניסה שמאוחסנים בתת-דומיין אחר באמצעות Credential Management API. לדוגמה, אם סיסמה מאוחסנת ב-login.example.com, סקריפט ב-www.example.com יכול להציג אותה כאחד מהפריטים של החשבון ב-Account Chooser.

צריך לשמור את הסיסמה באופן מפורש באמצעות navigator.credentials.store(), כדי שכאשר משתמש בוחר פרטי כניסה על ידי לחיצה על תיבת הדו-שיח, הסיסמה תועבר ותועתק למקור הנוכחי.

אחרי שהסיסמה נשמרת, היא זמינה כפרטי כניסה באותו מקור בדיוק www.example.com.

בצילום המסך הבא, פרטי הכניסה ששמורים ב-login.aliexpress.com גלויים ל-m.aliexpress.com והמשתמש יכול לבחור מביניהם:

Account Chooser שמציג את פרטי ההתחברות של תת-הדומיין שנבחר

‫Chrome 60

בגרסה 60 של Chrome יש כמה שינויים חשובים ב-Credential Management API:

נדרשת התייחסות לזיהוי התכונות

כדי לבדוק אם Credential Management API זמין לגישה לפרטי כניסה מבוססי-סיסמה ומאוחדים, בודקים אם window.PasswordCredential או window.FederatedCredential זמינים.

if (window.PasswordCredential || window.FederatedCredential) {
  // The Credential Management API is available
}

האובייקט PasswordCredential כולל עכשיו סיסמה

ה-Credential Management API נקט גישה שמרנית לטיפול בסיסמאות. הוא הסתיר סיסמאות מ-JavaScript, ודרש מהמפתחים לשלוח את האובייקט PasswordCredential ישירות לשרת שלהם לאימות באמצעות תוסף ל-API של fetch().

אבל הגישה הזו יצרה כמה מגבלות. קיבלנו משוב ממפתחים שלא הצליחו להשתמש ב-API כי:

  • הם היו צריכים לשלוח את הסיסמה כחלק מאובייקט JSON.

  • הם היו צריכים לשלוח את ערך ה-hash של הסיסמה לשרת שלהם.

ביצענו ניתוח אבטחה וגילינו שהסתרת סיסמאות מ-JavaScript לא מנעה את כל וקטורי התקיפה בצורה יעילה כמו שקיווינו, ולכן החלטנו לבצע שינוי.

ה-Credential Management API כולל עכשיו סיסמה גולמית באובייקט של פרטי הכניסה שמוחזר, כך שיש לכם גישה אליה כטקסט פשוט. אתם יכולים להשתמש בשיטות קיימות כדי להעביר את פרטי הכניסה לשרת:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(passwordCred => {
    if (passwordCred) {
    let form = new FormData();
    form.append('email', passwordCred.id);
    form.append('password', passwordCred.password);
    form.append('csrf_token', csrf_token);
    return fetch('/signin', {
        method: 'POST',
        credentials: 'include',
        body: form
    });
    } else {

    // Fallback to sign-in form
    }
}).then(res => {
    if (res.status === 200) {
    return res.json();
    } else {
    throw 'Auth failed';
    }
}).then(profile => {
    console.log('Auth succeeded', profile);
});

האפשרות לאחזור בהתאמה אישית תצא משימוש בקרוב

כדי לבדוק אם אתם משתמשים בפונקציה מותאמת אישית של fetch(), צריך לבדוק אם היא משתמשת באובייקט PasswordCredential או באובייקט FederatedCredential כערך של המאפיין credentials, לדוגמה:

fetch('/signin', {
    method: 'POST',
    credentials: c
})

מומלץ להשתמש בפונקציה רגילה של fetch(), כמו בדוגמת הקוד הקודמת, או להשתמש ב-XMLHttpRequest.

עד גרסה 60 של Chrome, הפונקציה navigator.credentials.get() קיבלה מאפיין unmediated אופציונלי עם דגל בוליאני. לדוגמה:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    unmediated: true
}).then(c => {

    // Sign-in
});

ההגדרה unmediated: true מונעת מהדפדפן להציג את Account Chooser כשמעבירים פרטי כניסה.

התכונה הזו הורחבה ועכשיו היא נקראת "מנגנון בחירת הרשת". הגישור בין המשתמשים יכול להתרחש במקרים הבאים:

  • המשתמש צריך לבחור חשבון כדי להיכנס.

  • משתמש רוצה להיכנס לחשבון באופן מפורש אחרי קריאה ל-navigator.credentials.requireUseMediation().

בוחרים אחת מהאפשרויות הבאות לערך mediation:

ערך של mediation בהשוואה לדגל בוליאני התנהגות
silent שווה ל-unmediated: true פרטי הכניסה הועברו בלי להציג את Account Chooser.
optional שווה ל-unmediated: false הצגת בורר חשבונות אם preventSilentAccess() נקרא בעבר.
required אפשרות חדשה תמיד להציג את בורר החשבונות. ‫האפשרות הזו שימושית כשרוצים לאפשר למשתמש להחליף חשבון באמצעות תיבת הדו-שיח המקורית לבחירת חשבון.

בדוגמה הזו, פרטי הכניסה מועברים בלי להציג את Account Chooser, בדומה לדגל הקודם, unmediated: true:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(c => {

    // Sign-in
});

השם של requireUserMediation() השתנה לשם preventSilentAccess()

כדי להתאים לנכס החדש mediation שמוצע בקריאה ל-get(), השם של ה-method‏ navigator.credentials.requireUserMediation() שונה ל-navigator.credentials.preventSilentAccess().

השיטה ששמה שונה מונעת העברה של פרטי כניסה בלי להציג את Account Chooser (לפעמים נקראת "ללא תיווך של המשתמש"). האפשרות הזו שימושית כשמשתמש יוצא מאתר או מבטל את הרישום לאתר, ולא רוצה להיכנס אליו שוב באופן אוטומטי בביקור הבא.

signoutUser();
if (navigator.credentials) {
    navigator.credentials.preventSilentAccess();
}

יצירת אובייקטים של פרטי כניסה באופן אסינכרוני באמצעות השיטה החדשה navigator.credentials.create()

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

יצירת אובייקט PasswordCredential

גישת הסנכרון
let c = new PasswordCredential(form);
גישה אסינכרונית (חדש)
let c = await navigator.credentials.create({
    password: form
});

או:

let c = await navigator.credentials.create({
    password: {
    id: id,
    password: password
    }
});

יצירת אובייקט FederatedCredential

גישת הסנכרון
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
גישה אסינכרונית (חדש)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

מדריך להעברת נתונים (מיגרציה)

כבר הטמעתם את Credential Management API? יש לנו מסמך הדרכה להעברת נתונים שאתם יכולים להיעזר בו כדי לשדרג לגרסה החדשה.