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 推出了幾項重要異動:

功能偵測功能需要處理

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

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

PasswordCredential 物件現在包含密碼

Credential Management API 會以保守的方式處理密碼。應用程式會隱藏 JavaScript 的密碼,要求開發人員將 PasswordCredential 物件直接傳送至其伺服器,以便透過擴充功能傳送至 fetch() API 進行驗證。

但此方法引發了幾項限制。我們收到開發人員的意見回饋,指出 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 嗎?您可以參閱這份遷移指南文件,瞭解如何升級至新版本。