FedCM 更新:Login Status API、Error API 和 Auto-selected Flag API

Chrome 120 即將針對 FedCM 提供 Login Status API。 登入狀態 API (舊稱 IdP 登入狀態 API) 可讓網站 (尤其是識別資訊提供者) 在使用者登入和登出時,向瀏覽器發出信號。FedCM 會使用這個信號解決無訊息的時間攻擊問題,如此一來,FedCM 就能不使用第三方 Cookie 的情況下運作。本次更新解決了我們先前在原始意圖傳送至 FedCM 的意圖中,最後發現的剩餘回溯不相容變更,這是我們工作範圍的一部分。

雖然 Login Status API 提升了隱私權屬性和可用性,但變更在出貨後具有回溯相容性。如果您目前已經實作 FedCM,請務必按照下列操作說明進行更新。

此外,Chrome 也提供兩項新的 Federated Credential Management (FedCM) 功能:

  • Error API:根據 ID 斷言端點的伺服器回應 (如果有的話),在使用者登入嘗試失敗時,通知使用者。
  • Auto-Selected Flag API:如果在流程中自動選取憑證,請通知識別資訊提供者 (IdP) 和依賴方 (RP)。

登入狀態 API

Login Status API 是一種機制,網站 (尤其是 IdP) 會通知瀏覽器使用者在 IdP 上的登入狀態。借助這個 API,瀏覽器可以減少對 IdP 發出不必要的要求,並減少潛在的時間攻擊。

通知瀏覽器使用者的登入狀態

當使用者在 IdP 上登入,或使用者登出所有 IdP 帳戶時,IdP 便可傳送 HTTP 標頭或呼叫 JavaScript API,向瀏覽器指出使用者的登入狀態。對於每個 IdP (透過設定網址識別),瀏覽器會保留代表登入狀態的三狀態變數,其中包含可能的值 logged-inlogged-outunknown。預設狀態為 unknown

如要表示使用者已登入,請在頂層導覽或相同來源子資源要求中傳送 Set-Login: logged-in HTTP 標頭:

Set-Login: logged-in

或者,您也可以從 IdP 來源呼叫 JavaScript API navigator.login.setStatus('logged-in')

navigator.login.setStatus('logged-in');

這些通話會將使用者的登入狀態記錄為 logged-in。當使用者的登入狀態設為 logged-in 時,呼叫 FedCM 的 RP 向 IdP 的帳戶清單端點提出要求,並在 FedCM 對話方塊中向使用者顯示可用帳戶。

如要表示使用者已登出所有帳戶,請傳送頂層導覽或相同來源子資源要求中的 Set-Login: logged-out HTTP 標頭:

Set-Login: logged-out

或者,您也可以從 IdP 來源呼叫 JavaScript API navigator.login.setStatus('logged-out')

navigator.login.setStatus('logged-out');

這些通話會將使用者的登入狀態記錄為 logged-out。當使用者的登入狀態為 logged-out 時,呼叫 FedCM 會失敗,而不會向 IdP 的帳戶清單端點提出要求。

unknown 狀態已設定在 IdP 使用 Login 狀態 API 傳送信號之前。我們推出了這個狀態,以便改善轉換作業,因為我們在提供這個 API 時,使用者可能已經登入 IdP。首次叫用 FedCM 時,IdP 可能無法向瀏覽器傳送信號。在這種情況下,我們會向 IdP 的帳戶清單端點發出要求,並根據帳戶清單端點的回應更新狀態:

  • 如果端點會傳回有效帳戶清單,請將狀態更新為 logged-in,然後開啟 FedCM 對話方塊來顯示這些帳戶。
  • 如果端點沒有傳回任何帳戶,請將狀態更新為 logged-out,並導致 FedCM 呼叫失敗。

如果使用者工作階段過期,會發生什麼情況?讓使用者透過動態登入流程登入!

即使 IdP 會持續將使用者的登入狀態告知瀏覽器,狀態也可能不會同步 (例如工作階段到期時)。當登入狀態為 logged-in 時,瀏覽器會嘗試將含有憑證的要求傳送至帳戶清單端點,但伺服器因工作階段已無法使用而未傳回任何帳戶。在這種情況下,瀏覽器可以動態讓使用者透過對話方塊視窗登入 IdP。

FedCM 對話方塊會顯示建議登入的訊息,如下圖所示。

建議登入 IdP 的 FedCM 對話方塊。
建議登入 IdP 的 FedCM 對話方塊。

當使用者按一下「Continue」按鈕時,瀏覽器會開啟 IdP 的登入頁面的對話方塊。

對話方塊範例。
點選「Sign in to IdP」按鈕後顯示的對話方塊範例。

登入頁面網址在 IdP 設定檔中已使用 login_url 指定。

{
  "accounts_endpoint": "/auth/accounts",
  "client_metadata_endpoint": "/auth/metadata",
  "id_assertion_endpoint": "/auth/idtokens",
  "login_url": "/login"
  }
}

對話方塊是含有第一方 Cookie 的一般瀏覽器視窗。無論對話方塊中的內容取決於 IdP,且沒有視窗控點,都可用來向 RP 頁面發出跨來源通訊要求。使用者登入後,IdP 應能執行下列操作:

  • 傳送 Set-Login: logged-in 標頭或呼叫 navigator.login.setStatus("logged-in") API,通知瀏覽器使用者已登入。
  • 呼叫 IdentityProvider.close() 即可關閉對話方塊。
使用者透過 FedCM 登入 IdP 後,登入 RP。
使用者透過 FedCM 登入 IdP 後,登入 RP。

您可以試用我們的示範來試用 Login 狀態 API 行為。

  1. 輕觸「Go to the IdP and sign in」按鈕。
  2. 使用任意帳戶登入。
  3. 從「帳戶狀態」下拉式選單中選取「工作階段已過期」
  4. 按下「更新個人資訊」按鈕。
  5. 輕觸「前往 RP 試用 FedCM」按鈕。

您應該可以透過模組行為觀察 IdP 的登入活動。

錯誤 API

當 Chrome 傳送要求至 ID 宣告端點時 (例如,當使用者點選 FedCM UI 上的「Continue as」按鈕,或觸發自動重新驗證時),IdP 可能會因正當理由無法核發權杖。 舉例來說,如果用戶端未經授權,伺服器暫時無法使用等。目前,Chrome 會在遇到這類錯誤時以無訊息方式失敗要求,並且只會拒絕 promise 來通知 RP。

使用 Error API 時,Chrome 會顯示原生 UI 以及 IdP 提供的錯誤資訊,進而通知使用者。

FedCM 對話方塊,在使用者嘗試登入失敗後顯示錯誤訊息。字串與錯誤類型相關。
FedCM 對話方塊在使用者嘗試登入失敗後顯示錯誤訊息。字串與錯誤類型相關。

IdP HTTP API

id_assertion_endpoint 回應中,如果可以依要求核發權杖,IdP 就可以將權杖傳回瀏覽器。在本提案中,萬一無法核發權杖,IdP 可以傳回「錯誤」回應,其中包含兩個新的選用欄位:

  1. code
  2. url
// id_assertion_endpoint response
{
  "error": {
     "code": "access_denied",
     "url": "https://idp.example/error?type=access_denied"
  }
}

針對程式碼,IdP 可以從 OAuth 2.0 指定的錯誤清單 [invalid_requestunauthorized_clientaccess_deniedserver_errortemporarily_unavailable] 中選擇其中一個已知錯誤,或使用任意字串。如果設為後者,Chrome 會顯示錯誤 UI 並顯示一般錯誤訊息,並將代碼傳遞至 RP。

針對 url,其可識別人類可讀的網頁,其中含有錯誤相關資訊,以便為使用者提供錯誤相關額外資訊。這個欄位對使用者非常實用,因為瀏覽器無法在原生 UI 中提供複合式錯誤訊息。例如後續步驟的連結、客戶服務聯絡資訊等。如果使用者想進一步瞭解錯誤詳細資料和修正方式,可以透過瀏覽器使用者介面造訪您提供的頁面瞭解詳情。網址必須與 IdP configURL 的相同網站相同。

try {
  const cred = await navigator.credentials.get({
    identity: {
      providers: [
        {
          configURL: 'https://idp.example/manifest.json',
          clientId: '1234',
        },
      ],
    }
  });
} catch (e) {
  const code = e.code;
  const url = e.url;
}

自動選取的旗標 API

mediation: optional 是 Credential Management API 中的預設使用者中介服務行為,會在可能的情況下觸發自動重新驗證機制。不過,由於只有瀏覽器才會知道,自動重新驗證可能無法使用。在無法使用時,系統可能會提示使用者以明確使用者中介服務登入,此流程包含不同屬性。

  • 從 API 呼叫端的角度來看,當他們收到 ID 權杖時,無法查看其是否為自動重新驗證流程的結果。因此,他們很難評估 API 效能,並據此改善使用者體驗。
  • 從 IdP 的角度來看,他們也無法判斷是否進行自動重新驗證,因此無法進行效能評估。此外,如果涉及明確的使用者中介服務,將有助於支援更多安全性相關功能。舉例來說,部分使用者可能偏好較高的安全性層級,因而需要在驗證時明確取得使用者中介服務。如果 IdP 收到的憑證要求未使用此類中介服務,則能以不同的方式處理要求。例如,傳回錯誤代碼,讓 RP 可以使用 mediation: required 再次呼叫 FedCM API。

因此,提供自動重新驗證流程的瀏覽權限,對開發人員很有助益。

使用 Auto-selected Flag API 時,每當發生自動重新驗證或明確中介服務時,Chrome 會與 IdP 和 RP 同時輕觸「Continue as」按鈕,藉此分享是否已取得明確的使用者權限。只有在使用者授予 IdP/RP 通訊的權限後,才會分享。

IdP 共用

如要將資訊分享給 IdP 貼文使用者權限,Chrome 會在傳送至 id_assertion_endpointPOST 要求中加入 is_auto_selected=true

POST /fedcm_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

account_id=123&client_id=client1234&nonce=Ct0D&disclosure_text_shown=true&is_auto_selected=true

受限方共享

瀏覽器可透過 IdentityCredential 將資訊提供給 isAutoSelected 中的 RP:

const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/manifest.json',
      clientId: '1234'
    }]
  }
});

if (cred.isAutoSelected !== undefined) {
  const isAutoSelected = cred.isAutoSelected;
}

交流及分享意見回饋

如有任何意見回饋或在測試期間遇到任何問題,可以前往 crbug.com 與我們分享。

Girl with Red hat (由 Unsplash 網站上提供)