呼叫 get() 方法
RP 可以呼叫 navigator.credentials.get() 並帶有 identity 選項,以請求使用者獲得使用現有 IdP 賬戶(他們在瀏覽器中已登入的賬戶)登入 RP 的選項。IdP 透過其 clientId 識別 RP,該 clientId 由每個 IdP 透過單獨的 IdP 特定過程頒發給 RP。所選的 IdP 會識別在登入流程中透過提供給瀏覽器的憑據(Cookie)嘗試登入的特定使用者。
如果所選 IdP 成功驗證了使用者身份,該方法將返回一個 Promise,該 Promise 將解析為 IdentityCredential 物件。此物件包含一個令牌,其中包含已用 IdP 的數字證書簽名的使用者身份資訊。
RP 將令牌傳送到其伺服器以驗證證書,成功後可以使用令牌中(現在受信任的)身份資訊將其登入到其服務(開始新會話),如果他們是新使用者,則將其註冊到其服務,等等。
如果使用者從未登入 IdP 或已登出,則 get() 方法將因錯誤而拒絕,並且 RP 可以將使用者引導至 IdP 頁面以登入或建立賬戶。
注意:驗證令牌的確切結構和內容對 FedCM API 和瀏覽器而言是透明的。IdP 決定其語法和用法,RP 需要遵循 IdP 提供的說明(例如,請參閱在您的伺服器端驗證 Google ID 令牌),以確保正確使用它。
一個典型的請求可能如下所示:
async function signIn() {
const identityCredential = await navigator.credentials.get({
identity: {
context: "signup",
providers: [
{
configURL: "https://accounts.idp.example/config.json",
clientId: "********",
nonce: "******",
loginHint: "user1@example.com",
},
{
// ...
},
],
},
});
}
identity.providers 屬性接受一個數組,其中包含一個或多個物件,指定每個 IdP 配置檔案(configURL)的路徑和 IdP 頒發給 RP 的客戶端識別符號(clientId)。
前面的示例還包含一些可選功能
identity.context指定使用者透過 FedCM 進行身份驗證的上下文。例如,是該賬戶的首次註冊,還是使用現有賬戶登入?瀏覽器使用此資訊來改變其 FedCM UI 中的文字,以更好地適應上下文。nonce屬性提供一個隨機 nonce 值,該值確保響應是為此特定請求發出的,從而防止重放攻擊。loginHint屬性提供關於瀏覽器應為使用者登入顯示的賬戶選項的提示。此提示與 IdP 在賬戶列表端點提供的login_hints值匹配。
瀏覽器請求 IdP 配置檔案並執行下面詳述的登入流程。有關使用者可能期望的瀏覽器提供的 UI 互動型別的更多資訊,請參閱 使用身份提供商登入信賴方。
FedCM 登入流程
登入流程涉及三方——RP 應用程式、瀏覽器本身和 IdP。下圖直觀地總結了正在發生的事情。

流程如下:
-
RP 呼叫
navigator.credentials.get()以啟動登入流程。 -
根據每個 IdP 提供的
configURL,瀏覽器請求兩個檔案:- 眾所周知的檔案 (
/.well-known/web-identity),可從configURL的 eTLD+1 處的/.well-known/web-identity獲取。 - IdP 配置檔案 (
/config.json),可從configURL獲取。
這些都是
GET請求,不帶 Cookie 且不遵循重定向。這有效地阻止了 IdP 瞭解是誰發出了請求以及哪個 RP 正在嘗試連線。透過 FedCM 從瀏覽器傳送的所有請求都包含一個
標頭,以防止 CSRF 攻擊。所有 IdP 端點都必須確認包含此標頭。Sec-Fetch-Dest: webidentity - 眾所周知的檔案 (
-
IdP 響應請求的眾所周知檔案和
config.json檔案。瀏覽器將get()請求中的配置檔案 URL 與眾所周知檔案中有效配置檔案 URL 列表進行驗證。 -
如果瀏覽器將 IdP 的登入狀態設定為
"logged-in",它將向 IdP 配置檔案中的accounts_endpoint發出憑據請求(即,帶有識別已登入使用者的 Cookie)以獲取使用者賬戶詳細資訊。這是一個帶 Cookie 但不帶client_id引數或Origin標頭的GET請求。這有效地阻止了 IdP 瞭解使用者正在嘗試登入哪個 RP。因此,返回的賬戶列表與 RP 無關。注意:如果所有 IdP 的登入狀態都是
"logged-out",則get()呼叫將因NetworkErrorDOMException而拒絕,並且不會向任何 IdP 的accounts_endpoint發出請求。在這種情況下,由開發人員處理流程,例如提示使用者去登入合適的 IdP。請注意,拒絕可能會有一些延遲,以避免將 IdP 登入狀態洩露給 RP。 -
IdP 響應從其
accounts_endpoint請求的賬戶資訊。這些是與使用者 IdP Cookie 關聯的所有賬戶的陣列,適用於與 IdP 關聯的任何 RP。 -
可選 如果包含在 IdP 配置檔案中,瀏覽器將向
client_metadata_endpoint發出無憑據請求,以獲取 RP 服務條款和隱私政策頁面的位置。這是一個GET請求,將get()呼叫中傳入的clientId作為引數傳送,不帶 Cookie。 -
可選 IdP 響應從
client_metadata_endpoint請求的 URL。 -
瀏覽器使用前兩組請求獲取的資訊來建立 UI,要求使用者選擇一個 IdP(如果已登入多個)和一個賬戶來登入 RP。UI 還要求使用者授予許可權,允許使用他們選擇的聯合 IdP 賬戶登入 RP。
-
如果使用者授予許可權,瀏覽器將向
id_assertion_endpoint發出憑據請求,以從所選 IdP 請求所選賬戶的驗證令牌。憑據以 HTTP
POST請求傳送,帶有 Cookie 和application/x-www-form-urlencoded的內容型別。如果呼叫失敗,將返回一個錯誤負載,如ID 斷言錯誤響應中所述,並且
get()返回的 Promise 將因錯誤而拒絕。 -
所選 IdP 會檢查 RP 傳送的賬戶 ID 是否與已登入賬戶的 ID 匹配,並且
Origin是否與 RP 的來源匹配,後者已提前在 IdP 中註冊。如果一切正常,它將響應請求的驗證令牌。注意:RP 的來源將在 RP 首次與 IdP 整合時透過一個完全獨立的過程在 IdP 中註冊。此過程將特定於每個 IdP。
-
當流程完成時,
get()Promise 將解析為IdentityCredential物件,該物件提供進一步的 RP 功能。最值得注意的是,此物件包含一個令牌,RP 可以驗證該令牌來自 IdP(使用證書)幷包含有關已登入使用者的受信任資訊。一旦 RP 驗證了令牌,他們就可以使用其中包含的資訊來登入使用者並開始新會話,將他們註冊到其服務,等等。令牌的格式和結構取決於 IdP,與 FedCM API 無關(RP 需要遵循 IdP 的說明)。
主動模式與被動模式
當 RP 使用者透過 FedCM API 登入時,瀏覽器可以提供兩種不同的 UI 模式:active 和 passive 模式。用於登入的模式由 identity 物件的 mode 選項控制
async function signIn() {
const identityCredential = await navigator.credentials.get({
identity: {
mode: active,
providers: [
{
configURL: "https://accounts.idp.example/config.json",
clientId: "********",
},
],
},
});
}
mode 的預設值為 passive。如果未設定 mode,或者明確設定為 passive,則瀏覽器可以透過 get() 呼叫啟動登入流程,而無需直接使用者互動。例如,您可能希望在使用者導航到登入頁面後立即啟動登入流程,前提是他們有 IdP 賬戶可以登入。在此模式下,瀏覽器通常會向用戶顯示一個登入對話方塊,其中包含 providers 物件中指定的所有不同登入選項,使用者可以選擇最適合他們的選項,然後輸入相應的憑據。
如果 mode 設定為 active,則瀏覽器要求透過使用者操作(例如單擊按鈕,需要瞬態啟用)啟動登入流程,並且 providers 物件的長度只能為 1,否則 get() Promise 將被拒絕。此模式通常在 RP 希望為每個 IdP 選擇提供單獨的按鈕時使用。當用戶單擊其中一個按鈕時,會出現一個簡化的對話方塊,只需他們輸入該賬戶的憑據。
有關 Google Chrome 中如何呈現不同 UI 模式的示例,請參閱 privacysandbox.google.com 上的 FedCM UI 模式。
自動重新認證
FedCM 自動重新認證允許使用者在首次使用 FedCM 認證後再次嘗試登入 RP 時自動重新認證。"首次認證"是指使用者在 RP 站點上的同一瀏覽器例項中,透過 FedCM 登入對話方塊首次建立賬戶或登入 RP 網站。
首次認證後,可以使用自動重新認證再次自動登入 RP 網站,而無需向用戶顯示“繼續為…”確認提示。如果使用者最近已授予許可權以允許使用特定賬戶進行聯合登入,則立即強制執行另一個明確的使用者確認在隱私或安全方面沒有任何好處。
自動重新認證行為由 get() 呼叫中的 mediation 選項控制
async function signIn() {
const identityCredential = await navigator.credentials.get({
identity: {
providers: [
{
configURL: "https://accounts.idp.example/config.json",
clientId: "********",
},
],
},
mediation: "optional", // this is the default
});
// isAutoSelected is true if auto-reauthentication occurred.
const isAutoSelected = identityCredential.isAutoSelected;
}
如果 mediation 設定為 optional 或 silent,則可以發生自動重新認證。
在以下條件下,將使用這些 mediation 選項進行自動重新認證:
- FedCM 可用。例如,使用者未全域性停用 FedCM 或在 RP 設定中停用 FedCM。
- 使用者僅在此瀏覽器上透過 FedCM 使用一個賬戶登入到 RP 網站。如果存在多個 IdP 的賬戶,使用者將不會自動重新認證。
- 使用者已使用該賬戶登入到 IdP。
- 自動重新認證在過去 10 分鐘內沒有發生。此限制旨在阻止使用者在登出後立即自動重新認證——這會造成非常令人困惑的使用者體驗。
- RP 在上次登入後沒有呼叫
preventSilentAccess()。RP 可以使用此功能根據需要明確停用自動重新認證。 - UI 模式為被動。
當滿足這些條件時,一旦呼叫 get(),就會嘗試自動重新認證使用者。如果自動重新認證成功,使用者將再次登入 RP 站點,而無需顯示確認提示,並使用與之前相同的 IdP 賬戶和已驗證的令牌。
如果自動重新認證失敗,行為取決於所選的 mediation 值:
optional:使用者將顯示對話方塊並再次要求確認。因此,此選項通常適用於使用者旅程未處於中途的頁面,例如 RP 登入頁面。silent:get()Promise 將被拒絕,開發人員需要處理引導使用者返回登入頁面以重新開始該過程。此選項適用於使用者旅程正在進行中且您需要讓他們保持登入直到完成的頁面,例如電子商務網站結賬流程的頁面。
注意:IdentityCredential.isAutoSelected 屬性指示聯合登入是否使用自動重新認證進行。這有助於評估 API 效能並相應地改進使用者體驗。此外,當它不可用時,可能會提示使用者透過顯式使用者中介(即 mediation: required 的 get() 呼叫)登入。
斷開聯合登入
RP 可以透過呼叫 IdentityCredential.disconnect() 將指定的聯合登入賬戶從關聯的 IdP 斷開。此函式可以從頂級 RP 框架呼叫。
IdentityCredential.disconnect({
configURL: "https://idp.example.com/config.json",
clientId: "rp123",
accountHint: "account456",
});
為了使 disconnect() 呼叫正常工作,IdP 必須在其配置檔案中包含一個 disconnect_endpoint。有關底層 HTTP 通訊的更多詳細資訊,請參閱斷開連線端點。
另見
- Federated Credential Management API on privacysandbox.google.com (2023)