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 之後同一來源中的憑證使用。

在以下螢幕截圖中,m.aliexpress.com 可以查看儲存在 login.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?我們提供遷移指南文件,您可以按照指示升級至新版本。