Federated Credential Management API 開發人員指南

瞭解如何使用 FedCM 保護隱私權的聯合身分識別功能。

FedCM (Federated Credential Management) 是聯合身分識別服務 (例如「使用...登入」) 的隱私權保護方法,可讓使用者登入網站而不將個人資訊提供給身分識別服務或網站。

如要進一步瞭解 FedCM 用途、使用者流程和 API 路線圖,請參閱 FedCM API 簡介

FedCM 開發環境

您必須在 Chrome 中的 IdP 和 RP 上建立安全內容 (HTTPS 或 localhost),才能使用 FedCM。

在 Android 版 Chrome 中對程式碼進行偵錯

在本機設定及執行伺服器,以便對 FedCM 程式碼進行偵錯。在連線的 Android 裝置上,您可以透過 USB 傳輸線搭配通訊埠轉送功能,在 Chrome 中存取這個伺服器

您可以使用電腦版的開發人員工具,按照「遠端偵錯 Android 裝置」中的指示,對 Android 上的 Chrome 進行偵錯。

在 Chrome 中封鎖第三方 Cookie

設定 Chrome 封鎖第三方 Cookie,模擬逐步淘汰第三方 Cookie
設定 Chrome 來封鎖第三方 Cookie,以模擬逐步淘汰第三方 Cookie

您可以在 FedCM 實際實施前,測試 FedCM 在 Chrome 上不使用第三方 Cookie 的運作方式。

如要封鎖第三方 Cookie,請使用無痕模式,或是在電腦版設定中選擇「封鎖第三方 Cookie」(chrome://settings/cookies),或在行動裝置上依序前往「設定」>「網站設定」>「Cookie」,選擇「封鎖第三方 Cookie」。

使用 FedCM API

您可以透過建立已知檔案設定檔和端點,針對帳戶清單斷言發出和選用的用戶端中繼資料,與 FedCM 整合。

接著,FedCM 會公開 JavaScript API,讓 RP 可用於與 IdP 登入

建立知名檔案

為避免追蹤器濫用 API,您必須從 IdP 的 eTLD+1/.well-known/web-identity 提供 well-known 檔案。

舉例來說,如果 IdP 端點是在 https://accounts.idp.example/ 下提供服務,則必須在 https://idp.example/.well-known/web-identity 中提供 well-known 檔案,以及IdP 設定檔。以下是已知檔案內容的範例:

{
  "provider_urls": ["https://accounts.idp.example/config.json"]
}

JSON 檔案必須包含 provider_urls 屬性,且內含 IdP 設定檔網址陣列,您可以依 RPs 在 navigator.credentials.get 中指定為 configURL 的路徑部分。陣列中的網址字串數量限制為一個,但日後可能會隨著您的意見回饋而改變。

建立 IdP 設定檔和端點

IdP 設定檔會提供瀏覽器所需的端點清單。IdP 會代管這個設定檔和必要的端點和網址。所有 JSON 回應都必須搭配 application/json 內容類型提供。

設定檔的網址是由提供給在 RP 上執行的 navigator.credentials.get 呼叫的值決定

const credential = await navigator.credentials.get({
  identity: {
    context: 'signup',
    providers: [{
      configURL: 'https://accounts.idp.example/config.json',
      clientId: '********',
      nonce: '******'
    }]
  }
});
const { token } = credential;

將 IdP 設定檔位置的完整網址指定為 configURL。在 RP 上呼叫 navigator.credentials.get() 時,瀏覽器會使用 GET 要求擷取設定檔,但不含 Origin 標頭或 Referer 標頭。這項要求沒有 Cookie,也不會追蹤重新導向。這樣即可有效防止 IdP 得知提出要求的使用者和嘗試連線的 RP。例如:

GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity

瀏覽器會預期來自 IdP 的 JSON 回應,其中包含下列屬性:

屬性 說明
accounts_endpoint (必填) 帳戶端點的網址。
client_metadata_endpoint (非必要) 用戶端中繼資料端點的網址。
id_assertion_endpoint (必填) ID 斷言端點的網址。
disconnect (非必要) 中斷連線端點的網址。
login_url (必填) 使用者用來登入 IdP 的登入頁面網址
branding (非必要) 包含各種品牌化選項的物件。
branding.background_color (非必要) 品牌宣傳選項,用於設定「繼續為...」按鈕的背景顏色。使用相關的 CSS 語法,例如 hex-colorhsl()rgb()named-color
branding.color (非必要) 品牌化選項,可設定「繼續以...身分登入」按鈕的文字顏色。使用相關的 CSS 語法,也就是 hex-colorhsl()rgb()named-color
branding.icons (非必要) 設定登入對話方塊中顯示的圖示物件品牌化選項。圖示物件是包含兩個參數的陣列:
  • url (必要):圖示圖片的網址。這項功能不支援 SVG 圖片。
  • size (選用):圖示尺寸,應用程式假設為正方形和單一解析度。這個數字必須大於或等於 25。

RP 可透過 navigator.credentials.get()identity.context 值,修改 FedCM 對話方塊 UI 中的字串,以配合預先定義的驗證內容。選用屬性可以是 "signin" (預設)、"signup""use""continue" 其中之一。

如何在 FedCM 對話方塊中套用品牌
如何將品牌資訊套用至 FedCM 對話方塊

以下是 IdP 的回應主體範例:

{
  "accounts_endpoint": "/accounts.php",
  "client_metadata_endpoint": "/client_metadata.php",
  "id_assertion_endpoint": "/assertion.php",
  "disconnect_endpoint": "/disconnect.php",
  "login_url": "/login",
  "branding": {
    "background_color": "green",
    "color": "#FFEEAA",
    "icons": [{
      "url": "https://idp.example/icon.ico",
      "size": 25
    }]
  }
}

瀏覽器擷取設定檔後,會將後續要求傳送至 IdP 端點:

IdP 端點
IdP 端點

帳戶端點

IdP 的帳戶端點會傳回使用者目前在 IdP 上登入的帳戶清單。如果 IdP 支援多個帳戶,這個端點會傳回所有已登入的帳戶。

瀏覽器傳送含有 SameSite=None 的 Cookie GET 要求,但沒有 client_id 參數、Origin 標頭或 Referer 標頭。這樣可以有效防止 IdP 得知使用者嘗試登入的 RP。例如:

GET /accounts.php HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

收到要求後,伺服器應:

  1. 確認要求包含 Sec-Fetch-Dest: webidentity HTTP 標頭。
  2. 將工作階段 Cookie 與已登入帳戶的 ID 比對。
  3. 在回應中提供帳戶清單。

瀏覽器會預期 JSON 回應包含 accounts 屬性,以及包含下列屬性的帳戶資訊陣列:

屬性 說明
id (必填) 使用者的專屬 ID。
name (必填) 使用者的名字和姓氏。
email (必填) 使用者的電子郵件地址。
given_name (非必要) 使用者的名字。
picture (非必要) 使用者顯示圖片的網址。
approved_clients (非必要) 使用者註冊的 RP 用戶端 ID 陣列。
login_hints (非必要) 陣列,其中包含 IdP 支援的所有可能篩選器類型,用於指定帳戶。RP 可以使用 loginHint 屬性叫用 navigator.credentials.get(),藉此有選擇性地顯示指定帳戶。
domain_hints (非必要) 帳戶相關聯的所有網域陣列。RP 可以使用 domainHint 屬性呼叫 navigator.credentials.get(),藉此篩選帳戶。

回應主體範例:

{
  "accounts": [{
    "id": "1234",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "approved_clients": ["123", "456", "789"],
    "login_hints": ["demo1", "demo1@idp.example"]
  }, {
    "id": "5678",
    "given_name": "Johnny",
    "name": "Johnny",
    "email": "johnny@idp.example",
    "picture": "https://idp.example/profile/456",
    "approved_clients": ["abc", "def", "ghi"],
    "login_hints": ["demo2", "demo2@idp.example"],
    "domain_hints": ["corp.example"]
  }]
}

如果使用者尚未登入,系統會傳回 HTTP 401 (Unauthorized) 回應。

傳回的帳戶清單會由瀏覽器使用,不會提供給 RP。

用戶端中繼資料端點

IdP 的用戶端中繼資料端點會傳回依賴方的中繼資料,例如 RP 的隱私權政策和服務條款。RP 應事先提供指向 IdP 的隱私權政策和服務條款連結。如果使用者尚未透過 IdP 在 RP 上註冊,這些連結就會顯示在登入對話方塊中。

瀏覽器會使用 client_id navigator.credentials.get 傳送 GET 要求,但不使用 Cookie。例如:

GET /client_metadata.php?client_id=1234 HTTP/1.1
Host: accounts.idp.example
Origin: https://rp.example/
Accept: application/json
Sec-Fetch-Dest: webidentity

收到要求後,伺服器應:

  1. 判斷 client_id 的 RP。
  2. 回應用戶端中繼資料。

用戶端中繼資料端點的屬性包括:

屬性 說明
privacy_policy_url (非必要) RP 隱私權政策網址。
terms_of_service_url (非必要) RP 服務條款網址。

瀏覽器預期端點會收到 JSON 回應:

{
  "privacy_policy_url": "https://rp.example/privacy_policy.html",
  "terms_of_service_url": "https://rp.example/terms_of_service.html",
}

傳回的用戶端中繼資料會由瀏覽器使用,且無法提供給 RP。

ID 斷言端點

IdP 的 ID 斷言端點會為已登入的使用者傳回宣告。 當使用者透過 navigator.credentials.get() 呼叫登入 RP 網站時,瀏覽器會將含有 Cookie 的 POST 要求 (內容類型為 application/x-www-form-urlencoded) 傳送至這個端點,並附上以下資訊:SameSite=None

屬性 說明
client_id (必填) 受限方的用戶端 ID。
account_id (必填) 登入使用者的專屬 ID。
nonce (非必要) RP 提供的要求 Nonce。
disclosure_text_shown 結果會是 "true""false" (而不是布林值) 的字串。如果未顯示揭露文字,結果會是 "false"。當帳戶端點的回應 approved_clients 屬性清單包含 RP 的用戶端 ID,或瀏覽器過去在沒有 approved_clients 的情況下觀察到註冊當下,就會發生這種情況。
is_auto_selected 如果對 RP 執行自動重新驗證is_auto_selected 表示 "true"。否則為 "false"。這樣就能支援更多安全性相關功能。舉例來說,有些使用者可能偏好更高的安全層級,這類層級需要在驗證時明確介入使用者。如果 IdP 收到的權杖要求未經過此類中介,則可能會以不同的方式處理要求。例如傳回錯誤代碼,讓 RP 可以再次使用 mediation: required 呼叫 FedCM API。

HTTP 標頭範例:

POST /assertion.php HTTP/1.1
Host: accounts.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=Ct60bD&disclosure_text_shown=true&is_auto_selected=true

收到要求後,伺服器應:

  1. 使用 CORS (跨來源資源共享) 回應要求。
  2. 確認要求包含 Sec-Fetch-Dest: webidentity HTTP 標頭。
  3. Origin 標頭與 client_id 決定的 RP 來源比對。如果不相符,請拒絕。
  4. account_id 與已登入帳戶的 ID 比對。如果不相符,則拒絕。
  5. 回傳符記。如果要求遭拒,請回應錯誤回應

憑證的核發方式取決於 IdP,但一般來說,系統會使用帳戶 ID、用戶端 ID、核發者來源、nonce 等資訊簽署憑證,讓 RP 驗證該符記是否正規。

瀏覽器會預期 JSON 回應包含下列屬性:

屬性 說明
token (必填) 憑證是包含驗證憑證附加資訊的字串。
{
  "token": "***********"
}

傳回的憑證會由瀏覽器傳遞至 RP,讓 RP 能夠驗證驗證。

傳回錯誤回應

id_assertion_endpoint 也可以傳回「錯誤」回應,其中包含兩個選用欄位:

  • code:IdP 可以從 OAuth 2.0 指定的錯誤清單 (invalid_requestunauthorized_clientaccess_deniedserver_errortemporarily_unavailable) 中選擇其中一個已知錯誤,或使用任意字串。如果較後者,Chrome 會使用一般錯誤訊息轉譯錯誤 UI,並將程式碼傳遞至 RP。
  • url:可識別人類可讀的網頁並提供錯誤相關資訊,以便為使用者提供該錯誤的額外資訊。這個欄位對使用者很有幫助,因為瀏覽器無法在原生 UI 中提供豐富的錯誤訊息。例如後續步驟連結、客戶服務聯絡資訊等。如果使用者想進一步瞭解錯誤詳細資料和修正方式,可以透過瀏覽器 UI 造訪提供的頁面,以取得更多資訊。這個網址必須與 IdP configURL 位於相同網站。
// id_assertion_endpoint response
{
  "error" : {
     "code": "access_denied",
     "url" : "https://idp.example/error?type=access_denied"
  }
}

中斷連線端點

透過叫用 IdentityCredential.disconnect(),瀏覽器會傳送跨來源 POST 要求,其中含有含有 SameSite=None 的 Cookie,以及 application/x-www-form-urlencoded 的內容類型,並將這些資訊傳送至這個斷開連線的端點:

屬性 說明
account_hint IdP 帳戶的提示。
client_id RP 的用戶端 ID。
POST /disconnect.php HTTP/1.1
Host: idp.example
Origin: rp.example
Content-Type: application/x-www-form-urlencoded
Cookie: 0x123
Sec-Fetch-Dest: webidentity

account_hint=account456&client_id=rp123

收到要求後,伺服器應:

  1. 使用 CORS (跨來源資源共享) 回應要求。
  2. 確認要求包含 Sec-Fetch-Dest: webidentity HTTP 標頭。
  3. Origin 標頭與 client_id 判定的受限方來源進行比對。如果不相符,則拒絕。
  4. account_hint 與已登入帳戶的 ID 進行比對。
  5. 將使用者帳戶與 RP 取消連結。
  6. 以 JSON 格式以 JSON 格式回應瀏覽器,提供已識別的使用者帳戶資訊。

回應 JSON 酬載的範例如下所示:

{
  "account_id": "account456"
}

如果 IdP 希望瀏覽器中斷所有與 RP 相關聯的帳戶,請傳遞與任何帳戶 ID 都不相符的字串,例如 "*"

登入網址

使用 Login Status API 時,IdP 必須向瀏覽器通知使用者的登入狀態。不過,狀態可能會不同步,例如在工作階段過期時。在這種情況下,瀏覽器可以透過 idp 設定檔login_url,讓使用者透過登入網頁網址動態登入 IdP。

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

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

當使用者按一下「Continue」按鈕時,瀏覽器會開啟 IdP 登入頁面的彈出式視窗。

FedCM 對話方塊範例。
點選登入 IdP 按鈕後顯示的對話方塊範例。

此對話方塊是擁有第一方 Cookie 的一般瀏覽器視窗。無論對話方塊中發生什麼事,都是由 IdP 組成,而且沒有視窗控點可用於向 RP 頁面提出跨來源通訊要求。使用者登入後,IdP 應:

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

通知瀏覽器使用者在身分識別提供者中的登入狀態

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

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

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

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 標頭,或在 IdP 來源傳送同網站子資源要求:

Set-Login: logged-out

您也可以在頂層導覽中,從 IdP 來源呼叫 JavaScript API navigator.login.setStatus("logged-out")

navigator.login.setStatus("logged-out")

這些呼叫會將使用者的登入狀態記錄為 logged-out。如果使用者的登入狀態為 logged-out,呼叫 FedCM 會在未向 IdP 的帳戶端點提出要求的情況下,以靜默方式失敗。

在 IdP 使用 Login Status API 傳送信號之前,系統會設定 unknown 狀態。Unknown 的推出可提供更佳的轉換體驗,因為使用者可能在這個 API 推出時已登入 IdP。在首次叫用 FedCM 時,IdP 可能無法向瀏覽器傳送這項信號。在這種情況下,Chrome 會向 IdP 的帳戶端點發出要求,並根據帳戶端點的回應更新狀態:

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

讓使用者透過動態登入流程登入

即使 IdP 持續向瀏覽器通知使用者的登入狀態,但在工作階段到期時,兩者可能會不同步。當登入狀態為 logged-in 時,瀏覽器會嘗試向帳戶端點傳送憑證要求,但伺服器不會傳回任何帳戶,因為工作階段已無法使用。在這種情況下,瀏覽器可以透過彈出式視窗,讓使用者以動態方式登入 IdP

透過識別資訊提供者登入依賴方

當 IdP 的設定和端點可供使用後,RP 就可以呼叫 navigator.credentials.get(),要求使用者透過 IdP 登入 RP。

呼叫 API 之前,您需要確認 [使用者瀏覽器上有 FedCM]。如要確認 FedCM 是否可用,請在 FedCM 實作中納入下列程式碼:

if ('IdentityCredential' in window) {
  // If the feature is available, take action
}

如要要求允許使用者從 RP 登入 IdP,請執行下列操作,例如:

const credential = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://accounts.idp.example/config.json',
      clientId: '********',
      nonce: '******'
    }]
  }
});
const { token } = credential;

providers 屬性會採用 IdentityProvider 物件的陣列,其中包含下列屬性:

屬性 說明
configURL (必填) IdP 設定檔的完整路徑。
clientId (必填) 由 IdP 核發的 RP 用戶端 ID。
nonce (非必要) 隨機字串,可確保系統針對這項特定要求發出回應。可防止重送攻擊。
loginHint (非必要) 指定 帳戶端點提供的 login_hints 值之一,FedCM 對話方塊就會依指定帳戶顯示。
domainHint (非必要) 透過指定帳戶端點提供的其中一個 domain_hints 值,FedCM 對話方塊就會選擇性顯示指定帳戶。

瀏覽器會根據 帳戶清單端點回應中是否存在 approved_clients,以不同方式處理註冊和登入用途。如果使用者已註冊 RP,瀏覽器不會顯示「To continue with ....」這個揭露文字。

系統會根據下列條件決定註冊狀態:

  • 如果 approved_clients 包含 RP 的 clientId
  • 如果瀏覽器記得使用者已註冊 RP。
使用者使用 FedCM 登入 RP。

當 RP 呼叫 navigator.credentials.get() 時,系統會執行下列活動:

  1. 瀏覽器會傳送要求並擷取多個文件:
    1. 已知檔案和宣告端點的 IdP 設定檔
    2. 帳戶清單
    3. 選用:從用戶端中繼資料端點擷取的 RP 隱私權政策和服務條款網址。
  2. 瀏覽器會顯示使用者可用來登入的帳戶清單,以及服務條款和隱私權政策 (如有)。
  3. 使用者選擇要登入的帳戶後,系統會將ID 宣告端點要求傳送至 IdP,以擷取權杖。
  4. RP 可以驗證權杖來驗證使用者。
登入 API 呼叫
login API 呼叫

RP 應支援不支援 FedCM 的瀏覽器,因此使用者應可使用現有的非 FedCM 登入程序。在逐步停用第三方 Cookie 之前,這個做法應該不會造成問題。

RP 伺服器驗證權杖後,RP 就可以註冊使用者,或讓他們登入並開始新的工作階段。

登入提示 API

使用者登入後,依賴方 (RP) 有時會要求使用者重新驗證。但使用者可能不確定自己使用的是哪個帳戶。如果 RP 可以指定要登入哪個帳戶,使用者就能更輕鬆地選取帳戶。

RP 可以使用 loginHint 屬性搭配 帳戶清單端點擷取的 login_hints 值之一,呼叫 navigator.credentials.get(),藉此選擇顯示特定帳戶,如以下程式碼範例所示:

return await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "123",
      nonce: nonce,
      loginHint : "demo1@example.com"
    }]
  }
});

如果沒有符合 loginHint 的帳戶,FedCM 對話方塊會顯示登入提示,讓使用者登入與 RP 要求的提示相符的 IdP 帳戶。使用者輕觸提示時,系統會開啟彈出式視窗,其中包含設定檔中指定的登入網址。這個連結會附加登入提示和網域提示查詢參數。

Domain Hint API

在某些情況下,RP 已知曉只有與特定網域相關聯的帳戶才能登入網站。這在企業情境中特別常見,因為存取的網站會限制在公司網域內。為了提供更優質的使用者體驗,FedCM API 允許 RP 只顯示可用於登入 RP 的帳戶。這可避免使用者嘗試使用公司網域以外的帳戶登入 RP,但因為未使用正確類型的帳戶,而導致稍後顯示錯誤訊息 (或登入失敗時保持沉默) 的情況。

RPs 可以選擇性地顯示只有相符的帳戶,方法是使用 domainHint 屬性叫用 navigator.credentials.get(),其中包含從帳戶清單端點擷取的其中一個 domain_hints 值,如以下程式碼範例所示:

return await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/manifest.json",
      clientId: "abc",
      nonce: nonce,
      domainHint : "corp.example"
    }]
  }
});

如果沒有任何帳戶與 domainHint 相符,FedCM 對話方塊會顯示登入提示,讓使用者登入與 RP 要求提示相符的 IdP 帳戶。使用者輕觸提示時,系統會開啟彈出式視窗,並以設定檔中指定的登入網址開啟。接著,連結會附加登入提示和網域提示查詢參數。

如果沒有帳戶與 domainHint 相符,系統會顯示登入提示範例。
沒有任何帳戶符合 domainHint 時的登入提示範例。

顯示錯誤訊息

有時,IdP 可能會基於正當理由而無法核發權杖,例如用戶端未經授權、伺服器暫時無法使用。如果 IdP 傳回「error」回應,RP 可以擷取該回應,Chrome 也會透過顯示瀏覽器 UI 通知使用者,並顯示 IdP 提供的錯誤資訊。

A
FedCM 對話方塊:在使用者登入失敗後顯示錯誤訊息。字串與錯誤類型相關聯。
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;
}

在初始驗證後自動重新驗證使用者

FedCM 自動重新驗證 (簡稱「auto-reauthn」) 可讓使用者在使用 FedCM 進行初次驗證後,自動重新驗證。此處的「初始驗證」是指使用者在同一個瀏覽器執行個體上首次輕觸 FedCM 登入對話方塊中的「以...繼續」按鈕,建立帳戶或登入 RP 網站。

雖然在使用者建立聯合帳戶來防止追蹤 (這是 FedCM 的主要目標之一) 前,明確使用者體驗是合理的,但在使用者進行過一次後,對於 RP 與 IdP 之間的通訊授予權限後,其隱私權或安全性的助益已無疑是對使用者已明確確認的隱私或安全好處。

透過自動重新驗證,瀏覽器會根據您在呼叫 navigator.credentials.get() 時為 mediation 指定的選項變更行為。

const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: "https://idp.example/fedcm.json",
      clientId: "1234",
    }],
  },
  mediation: 'optional', // this is the default
});

// `isAutoSelected` is `true` if auto-reauthn was performed.
const isAutoSelected = cred.isAutoSelected;

mediationCredential Management API 中的屬性,其行為PasswordCredentialFederatedCredential 相同,且受到 PublicKeyCredential 部分支援。屬性接受以下四個值:

  • 'optional' (預設):盡可能自動重新授權,否則需要中介服務。建議您在登入頁面上選擇這個選項。
  • 'required':一律需要中介服務才能繼續操作,例如按一下使用者介面上的「繼續」按鈕。如果您希望使用者每次需要驗證時都必須明確授予權限,請選擇這個選項。
  • 'silent':盡可能自動重新授權,如果無法自動重新授權,則在未要求仲裁的情況下,以靜默方式失敗。建議您在專屬登入頁面以外,但希望使用者保持登入狀態的網頁上選取這個選項,例如運送網站的商品頁面,或新聞網站的文章頁面。
  • 'conditional':用於 WebAuthn,目前不適用於 FedCM。

使用此呼叫時,系統會在下列情況下自動重新驗證:

在符合這些條件時,只要叫用 FedCM navigator.credentials.get(),系統就會嘗試自動重新驗證使用者。

設為 mediation: optional 時,由於只有瀏覽器知道的原因,可能無法使用自動重新驗證;RP 可以藉由檢查 isAutoSelected 屬性,檢查自動重新驗證是否執行了。

這有助於評估 API 效能,並據此改善使用者體驗。此外,如果無法使用,系統可能會提示使用者透過明確的使用者中介服務登入,也就是使用 mediation: required 的流程。

使用者透過 FedCM 自動重新驗證。

使用 preventSilentAccess() 強制執行中介服務

在使用者登出後立即自動重新驗證,並不會帶來良好的使用者體驗。因此,FedCM 會在自動重新授權後設有 10 分鐘的靜默期,以避免發生這種行為。也就是說,除非使用者在 10 分鐘內重新登入,否則自動重新授權的情況最多會發生 10 分鐘一次。當使用者明確登出 RP (例如點選登出按鈕),RP 應呼叫 navigator.credentials.preventSilentAccess(),明確要求瀏覽器停用自動重新授權。

function signout() {
  navigator.credentials.preventSilentAccess();
  location.href = '/signout';
}

使用者可以在設定中選擇不使用自動重新驗證

使用者可透過設定選單選擇停用自動重新授權功能:

  • 在 Chrome 電腦版中,依序前往 chrome://password-manager/settings > 自動登入。
  • 在 Android 版 Chrome 中,依序開啟「設定」>「密碼管理員」> 輕觸右上角的齒輪圖示 >「自動登入」。

只要停用切換鈕,使用者就能完全停用自動重新驗證行為。如果使用者在 Chrome 執行個體上登入 Google 帳戶,並啟用同步處理功能,這項設定會在所有裝置上保持同步並保持同步。

將 IdP 與 RP 中斷連線

如果使用者先前曾透過 FedCM 使用 IdP 登入 RP,瀏覽器會在本機將這項關係儲存為已連結帳戶的清單。RP 可能會透過呼叫 IdentityCredential.disconnect() 函式來啟動中斷連線。您可以從頂層 RP 頁框呼叫這個函式。RP 必須傳遞 configURL、其在 IdP 之下使用的 clientId,以及 accountHint,才能中斷 IdP 連線。只要斷開連結端點可識別帳戶,帳戶提示可以是任意字串,例如電子郵件地址或使用者 ID,不一定需要與帳戶清單端點提供的帳戶 ID 相符:

// Disconnect an IdP account "account456" from the RP "https://idp.com/". This is invoked on the RP domain.
IdentityCredential.disconnect({
  configURL: "https://idp.com/config.json",
  clientId: "rp123",
  accountHint: "account456"
});

IdentityCredential.disconnect() 會傳回 Promise。這項承諾可能會擲回例外狀況,原因如下:

  • 使用者尚未透過 FedCM 使用 IdP 登入 RP。
  • 這個 API 是從沒有 FedCM 權限政策的 iframe 中叫用。
  • configURL 無效,或缺少中斷連線的端點。
  • 無法執行內容安全政策 (CSP) 檢查。
  • 目前有待處理的取消連結要求。
  • 使用者已在瀏覽器設定中停用 FedCM。

IdP 的斷開連線端點傳回回應時,瀏覽器上的 RP 和 IdP 會中斷連線,且承諾會解析。系統會在中斷連線端點的回應中指定中斷連線帳戶的 ID。

從跨來源 iframe 中呼叫 FedCM

如果父項框架允許,您可以使用 identity-credentials-get 權限政策,從跨來源 iframe 內叫用 FedCM。方法是將 allow="identity-credentials-get" 屬性附加至 iframe 標記,如下所示:

<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>

您可以在範例中查看實際使用狀況。

或者,如果父項框架想要限制呼叫 FedCM 的來源,請傳送 Permissions-Policy 標頭,並附上允許的來源清單。

Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")

如要進一步瞭解權限政策的運作方式,請參閱「使用權限政策控管瀏覽器功能」。