瞭解如何使用 FedCM 保護隱私權的聯合身分識別功能。
FedCM (聯合憑證管理) 是一種隱私權保護方法,可用於聯合身分識別服務 (例如「使用...登入」),讓使用者不必與身分識別服務或網站分享個人資訊,即可登入網站。
如要進一步瞭解 FedCM 用途、使用者流程和 API 路線圖,請參閱 FedCM API 簡介。
FedCM 開發環境
您必須在 Chrome 中的 IdP 和 RP 上建立安全內容 (HTTPS 或 localhost),才能使用 FedCM。
在 Android 裝置上的 Chrome 上偵錯程式碼
在本機設定及執行伺服器,以便對 FedCM 程式碼進行偵錯。您可以使用 USB 傳輸線連接 Android 裝置,並在 Chrome 中存取這個伺服器,並透過連接埠轉送功能。
您可以使用電腦版的開發人員工具,按照「遠端偵錯 Android 裝置」中的指示,對 Android 上的 Chrome 進行偵錯。
在 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 指定為 configURL
在 navigator.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-color 、hsl() 、rgb() 或 named-color 。 |
branding.color (非必要) |
品牌化選項,可設定「繼續以...身分登入」按鈕的文字顏色。使用相關的 CSS 語法,也就是 hex-color 、hsl() 、rgb() 或 named-color 。 |
branding.icons (非必要) |
設定登入對話方塊中顯示的圖示物件品牌化選項。圖示物件是包含兩個參數的陣列:
|
RP 可以使用 navigator.credentials.get()
的 identity.context
值修改 FedCM 對話方塊 UI 中的字串,以便配合預先定義的驗證內容。選用屬性可以是 "signin"
(預設值)、"signup"
、"use"
或 "continue"
其中之一。
以下是 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 支援多個帳戶,這個端點會傳回所有已登入的帳戶。
瀏覽器傳送含有 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
收到要求後,伺服器應:
- 確認要求包含
Sec-Fetch-Dest: webidentity
HTTP 標頭。 - 將工作階段 Cookie 與已登入帳戶的 ID 比對。
- 回覆帳戶清單。
瀏覽器會預期 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
收到要求後,伺服器應:
- 判斷
client_id
的 RP。 - 回傳用戶端中繼資料。
用戶端中繼資料端點的屬性包括:
屬性 | 說明 |
---|---|
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
收到要求後,伺服器應:
- 使用 CORS (跨來源資源共享) 回應要求。
- 確認要求包含
Sec-Fetch-Dest: webidentity
HTTP 標頭。 - 將
Origin
標頭與client_id
所判定的 RP 來源比對。如果不相符,請拒絕。 - 將
account_id
與已登入帳戶的 ID 比對。如果不相符,請拒絕。 - 回傳符記。如果要求遭到拒絕,請傳送錯誤回應。
憑證的發出方式由 IdP 決定,但一般來說,憑證會使用帳戶 ID、用戶端 ID、發出者來源、nonce
等資訊進行簽署,以便 RP 驗證憑證是否為真。
瀏覽器會預期 JSON 回應包含下列屬性:
屬性 | 說明 |
---|---|
token (必填) |
權杖是包含驗證相關宣告的字串。 |
{
"token": "***********"
}
瀏覽器會將傳回的權杖傳遞給 RP,以便 RP 驗證驗證。
傳回錯誤回應
id_assertion_endpoint
也可以傳回「error」回應,其中包含兩個選填欄位:
code
:IdP 可以從 OAuth 2.0 指定的錯誤清單 (invalid_request
、unauthorized_client
、access_denied
、server_error
和temporarily_unavailable
) 中選擇一個已知錯誤,或使用任意字串。如果是後者,Chrome 會顯示含有一般錯誤訊息的錯誤 UI,並將代碼傳遞至 RP。url
:這個屬性會識別使用者可讀取的網頁,並提供錯誤資訊,以便向使用者提供錯誤的其他資訊。這個欄位對使用者來說很實用,因為瀏覽器無法在內建 UI 中提供豐富的錯誤訊息。例如:後續步驟的連結,或客戶服務聯絡資訊。如果使用者想進一步瞭解錯誤詳細資料和修正方式,可以透過瀏覽器 UI 造訪提供的頁面,瞭解更多詳情。這個網址必須與 IdPconfigURL
位於相同網站。
// 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
收到要求後,伺服器應:
- 使用 CORS (跨來源資源共享) 回應要求。
- 確認要求包含
Sec-Fetch-Dest: webidentity
HTTP 標頭。 - 將
Origin
標頭與client_id
所判定的 RP 來源比對。如果不相符,請拒絕。 - 將
account_hint
與已登入帳戶的 ID 比對。 - 將使用者帳戶與 RP 斷開連結。
- 以 JSON 格式回應瀏覽器,提供已識別的使用者帳戶資訊。
回應 JSON 酬載範例如下所示:
{
"account_id": "account456"
}
相反地,如果 IdP 希望瀏覽器取消連結與 RP 相關聯的所有帳戶,請傳遞不符合任何帳戶 ID 的字串,例如 "*"
。
登入網址
使用登入狀態 API 時,IdP 必須將使用者的登入狀態通知瀏覽器。不過,狀態可能會不同步,例如在工作階段過期時。在這種情況下,瀏覽器可以透過 idp 設定檔的 login_url
,讓使用者透過登入網頁網址動態登入 IdP。
FedCM 對話方塊會顯示建議登入的訊息,如以下圖所示。
使用者點選「Continue」按鈕後,瀏覽器會開啟 IdP 登入頁面的彈出式視窗。
對話方塊是含有第一方 Cookie 的一般瀏覽器視窗。對話方塊中的所有事件都由 IdP 處理,而且沒有可用來向 RP 頁面提出跨來源通訊要求的視窗句柄。使用者登入後,IdP 應:
- 傳送
Set-Login: logged-in
標頭或呼叫navigator.login.setStatus("logged-in")
API,通知瀏覽器使用者已登入。 - 呼叫
IdentityProvider.close()
即可關閉對話方塊。
通知瀏覽器使用者在身分識別提供者中的登入狀態
登入狀態 API 是一種機制,可讓網站 (尤其是 IdP) 向瀏覽器告知使用者在 IdP 上的登入狀態。有了這個 API,瀏覽器就能減少對 IdP 的不必要要求,並減輕潛在的時間攻擊。
當使用者登入 IdP 或登出所有 IdP 帳戶時,IdP 可以透過傳送 HTTP 標頭或呼叫 JavaScript API,向瀏覽器傳送使用者的登入狀態。對於每個 IdP (以其設定網址識別),瀏覽器會保留一個三態變數,代表登入狀態,可能的值為 logged-in
、logged-out
和 unknown
。預設狀態為 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。
當 RP 呼叫 navigator.credentials.get()
時,系統會執行下列活動:
- 瀏覽器會傳送要求並擷取多個文件:
- well-known 檔案和IdP 設定檔,用於宣告端點。
- 帳戶清單。
- 選用:從 用戶端中繼資料端點擷取的 RP 隱私權政策和服務條款網址。
- 瀏覽器會顯示使用者可用來登入的帳戶清單,以及服務條款和隱私權政策 (如有)。
- 使用者選擇要登入的帳戶後,系統會將要求傳送至 ID 斷言端點,並將憑證傳送至 IdP 以擷取權杖。
- RP 可以驗證權杖,以便驗證使用者。
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 帳戶。使用者輕觸提示時,系統會開啟彈出式視窗,其中包含設定檔中指定的登入網址。接著,連結會附加登入提示和網域提示查詢參數。
顯示錯誤訊息
有時,IdP 可能會基於正當理由而無法發出權杖,例如用戶端未經授權、伺服器暫時無法使用。如果 IdP 傳回「error」回應,RP 可以擷取該回應,Chrome 也會透過顯示瀏覽器 UI 通知使用者,並顯示 IdP 提供的錯誤資訊。
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;
mediation
是 Credential Management API 中的屬性,其行為與 PasswordCredential 和 FederatedCredential 相同,也部分支援 PublicKeyCredential。這個屬性可接受下列四個值:
'optional'
(預設):盡可能自動重新授權,否則需要中介服務。建議您在登入頁面中選擇這個選項。'required'
:一律需要仲介才能繼續,例如按一下 UI 上的「繼續」按鈕。如果您希望使用者每次需要驗證時都必須明確授予權限,請選擇這個選項。'silent'
:盡可能自動重新授權,如果無法自動重新授權,則在未要求仲裁的情況下,以靜默方式失敗。建議您在專屬登入頁面以外,但希望使用者保持登入狀態的網頁上選取這個選項,例如運送網站的商品頁面,或新聞網站的文章頁面。'conditional'
:用於 WebAuthn,目前無法用於 FedCM。
在這個呼叫中,系統會在下列情況下自動重新授權:
- FedCM 可供使用。例如,使用者並未在設定中為 FedCM 全域或 RP 停用。
- 使用者只使用一個具備 FedCM API 的帳戶,透過這個瀏覽器登入網站。
- 使用者已使用該帳戶登入 IdP。
- 自動重新授權未在過去 10 分鐘內發生。
- 在先前登入後,RP 並未呼叫
navigator.credentials.preventSilentAccess()
。
在符合這些條件時,只要叫用 FedCM navigator.credentials.get()
,系統就會嘗試自動重新驗證使用者。
當 mediation: optional
時,自動重新驗證可能會因只有瀏覽器知道的原因而無法使用;RP 可以檢查 isAutoSelected
屬性,確認是否已執行自動重新驗證。
這有助於評估 API 效能,並據此改善使用者體驗。此外,如果無法使用,系統可能會提示使用者透過明確的使用者中介服務登入,也就是使用 mediation: required
的流程。
使用 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")
如要進一步瞭解權限政策的運作方式,請參閱「透過權限政策控管瀏覽器功能」。