Federated Credential Management API 開發人員指南

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

FedCM (聯合憑證管理) 是一種隱私權保護方法,可用於聯合身分識別服務 (例如「使用...登入」),讓使用者不必與身分識別服務或網站分享個人資訊,即可登入網站。

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

FedCM 開發環境

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

在 Android 裝置上的 Chrome 上偵錯程式碼

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

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

在 Chrome 中封鎖第三方 Cookie

在 Chrome 設定中封鎖第三方 Cookie
在 Chrome 設定中封鎖第三方 Cookie

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

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

使用 FedCM API

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

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

建立 well-known 檔案

為避免追蹤器濫用 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 設定檔網址的陣列,可由 RP 指定為 configURLnavigator.credentials.get 中的路徑部分。陣列中的網址字串數量上限為 1,但日後可能會根據您的意見回饋而有所變動。

建立 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;

configURL 的形式指定 IdP 設定檔位置的完整網址。在 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 (未經授權)。

瀏覽器會使用傳回的帳戶清單,RP 無法使用。

用戶端中繼資料端點

IdP 的用戶端中繼資料端點會傳回依附方中繼資料,例如依附方的隱私權政策和服務條款。應用程式提供者應事先提供隱私權政策和服務條款的連結給 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 網站時,瀏覽器會傳送 POST 要求,其中包含含有 SameSite=None 的 Cookie,以及 application/x-www-form-urlencoded 的內容類型,並將以下資訊傳送至此端點:

屬性 說明
client_id (必填) RP 的用戶端 ID。
account_id (必填) 登入使用者的專屬 ID。
nonce (非必要) 由 RP 提供的要求 Nonce。
disclosure_text_shown 結果為 "true""false" 的字串 (而非布林值)。如果未顯示揭露資訊文字,結果會是 "false"。當 RP 的用戶端 ID 包含在 accounts 端點回應的 approved_clients 屬性清單中,或是瀏覽器在過去未有 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 也可以傳回「error」回應,其中包含兩個選填欄位:

  • 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 所判定的 RP 來源比對。如果不相符,請拒絕。
  4. account_hint 與已登入帳戶的 ID 比對。
  5. 將使用者帳戶與 RP 斷開連結。
  6. 以 JSON 格式回應瀏覽器,提供已識別的使用者帳戶資訊。

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

{
  "account_id": "account456"
}

相反地,如果 IdP 希望瀏覽器取消連結與 RP 相關聯的所有帳戶,請傳遞不符合任何帳戶 ID 的字串,例如 "*"

登入網址

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

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

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

使用者點選「Continue」按鈕後,瀏覽器會開啟 IdP 登入頁面的彈出式視窗。

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

對話方塊是含有第一方 Cookie 的一般瀏覽器視窗。對話方塊中的所有事件都由 IdP 處理,而且沒有可用來向 RP 頁面提出跨來源通訊要求的視窗句柄。使用者登入後,IdP 應:

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

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

登入狀態 API 是一種機制,可讓網站 (尤其是 IdP) 向瀏覽器告知使用者在 IdP 上的登入狀態。有了這個 API,瀏覽器就能減少對 IdP 的不必要要求,並減輕潛在的時間攻擊。

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

如要指出使用者已登入,請在頂層導覽或 IdP 來源的相同網站子資源要求中傳送 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 對話方塊中向使用者顯示可用的帳戶。

如要指出使用者已登出所有帳戶,請在頂層導覽或 IdP 來源的相同網站子資源要求中傳送 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 使用登入狀態 API 傳送信號前設定。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. well-known 檔案IdP 設定檔,用於宣告端點。
    2. 帳戶清單
    3. 選用:從 用戶端中繼資料端點擷取的 RP 隱私權政策和服務條款網址。
  2. 瀏覽器會顯示使用者可用來登入的帳戶清單,以及服務條款和隱私權政策 (如有)。
  3. 使用者選擇要登入的帳戶後,系統會將要求傳送至 ID 斷言端點,並將憑證傳送至 IdP 以擷取權杖。
  4. RP 可以驗證權杖,以便驗證使用者。
登入 API 呼叫
登入 API 呼叫

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

令牌經 RP 伺服器驗證後,RP 可能會註冊使用者,或讓使用者登入並開始新的工作階段。

Login Hint 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,但因為未使用正確類型的帳戶,而導致稍後顯示錯誤訊息 (或登入失敗時保持沉默) 的情況。

RP 可以使用 domainHint 屬性搭配 domain_hints 值 (從帳戶清單端點擷取) 呼叫 navigator.credentials.get(),只顯示符合條件的帳戶,如以下程式碼範例所示:

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 相符時的登入提示範例。

顯示錯誤訊息

有時,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':一律需要仲介才能繼續,例如按一下 UI 上的「繼續」按鈕。如果您希望使用者每次需要驗證時都必須明確授予權限,請選擇這個選項。
  • '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,以及用於斷開 IdP 的 accountHint。只要斷開連結端點可識別帳戶,帳戶提示可以是任意字串,例如電子郵件地址或使用者 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。
  • 在沒有 FedCM 權限政策的 iframe 中叫用 API。
  • configURL 無效或缺少斷開連線端點。
  • 內容安全政策 (CSP) 檢查失敗。
  • 有個待處理的斷線要求。
  • 使用者已在瀏覽器設定中停用 FedCM。

IdP 的斷開連線端點傳回回應時,瀏覽器上的 RP 和 IdP 會中斷連線,並解析承諾。取消連結端點的回應中會指定已取消連結的帳戶 ID。

從跨來源 iframe 中呼叫 FedCM

如果父項框架允許,您可以使用 identity-credentials-get 權限政策,從跨來源 iframe 內叫用 FedCM。如要這麼做,請在 iframe 代碼中附加 allow="identity-credentials-get" 屬性,如下所示:

<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")

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