credential Management API 最新消息

我們在 Google I/O 的「安全無縫登入:讓使用者持續參與」工作坊中,說明瞭這裡提到的部分更新:

Chrome 57

Chrome 57 為 Credential Management API 導入了這項重要變更。

憑證可從其他子網域共用

Chrome 現可使用 Credential Management API 擷取儲存在不同子網域中的憑證。舉例來說,如果密碼儲存在 login.example.com 中,www.example.com 上的指令碼就能在帳戶選擇器對話方塊中,將密碼顯示為帳戶項目之一。

您必須使用 navigator.credentials.store() 明確儲存密碼,這樣當使用者輕觸對話方塊選擇憑證時,系統就會傳送密碼並複製到目前的來源。

儲存後,密碼會在相同來源 www.example.com 之後,以憑證的形式提供。

在下列螢幕截圖中,login.aliexpress.com 底下儲存的憑證資訊會顯示在 m.aliexpress.com 中,供使用者選擇:

帳戶選擇工具顯示所選子網域的登入詳細資料

Chrome 60

Chrome 60 對 Credential Management API 進行了幾項重要變更:

需要注意功能偵測

如要查看是否可使用憑證管理 API 存取密碼和聯合式憑證,請檢查 window.PasswordCredentialwindow.FederatedCredential 是否可用。

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

PasswordCredential 物件現在包含密碼

Credential Management API 採用保守的密碼處理方式。這項功能會將密碼隱藏在 JavaScript 中,因此開發人員必須將 PasswordCredential 物件直接傳送至伺服器,透過 fetch() API 的擴充功能進行驗證。

但這種做法會帶來許多限制。我們收到開發人員無法使用 API 的意見回饋,原因如下:

  • 他們必須將密碼傳送為 JSON 物件的一部分。

  • 他們必須將密碼的雜湊值傳送至伺服器。

在執行安全性分析後,我們發現隱藏 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

在 Chrome 60 之前,navigator.credentials.get() 會接受帶有布林旗標的選用 unmediated 屬性。例如:

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

    // Sign-in
});

設定 unmediated: true 可防止瀏覽器在傳遞憑證時顯示帳戶選擇器。

標記現已擴充為中介服務。使用者中介服務可能會在下列情況下發生:

  • 使用者必須選擇要登入的帳戶。

  • 使用者希望在 navigator.credentials.requireUseMediation() 呼叫後明確登入。

請為 mediation 值選擇下列其中一個選項:

mediation 與布林值標記相比 行為
silent 等於 unmediated: true 系統未顯示帳戶選擇器,就傳遞了憑證。
optional 等於 unmediated: false 如果先前已呼叫 preventSilentAccess(),則會顯示帳戶選擇器。
required 新選項 一律顯示帳戶選擇器。 當您想讓使用者使用原生帳戶選擇器對話方塊切換帳戶時,此方法就很實用。

在這個範例中,系統會傳遞憑證,但不會顯示帳戶選擇器,這與先前的標記 unmediated: true 相同:

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

    // Sign-in
});

requireUserMediation() 已重新命名為 preventSilentAccess()

為配合 get() 呼叫中提供的新 mediation 屬性,navigator.credentials.requireUserMediation() 方法已重新命名為 navigator.credentials.preventSilentAccess()

重新命名的方法可避免在未顯示帳戶選擇器的情況下傳遞憑證 (有時稱為不經使用者中介)。當使用者從網站登出或取消註冊,且不想在下次造訪時自動登入時,這項功能就很實用。

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?我們提供遷移指南文件,您可以按照指示升級至新版本。