瞭解如何使用 FedCM 進行隱私權保護身分聯盟。
FedCM (Federated Credential Management) 是聯合身分識別服務 (例如「使用...登入」) 的隱私權保護做法,可讓使用者登入網站而不將個人資訊提供給身分識別服務或網站。
如要進一步瞭解 FedCM 用途、使用者流程和 API 發展藍圖,請參閱 FedCM API 簡介。
FedCM 開發環境
您必須在 Chrome 的 IdP 和 RP 上設定安全背景資訊 (HTTPS 或 localhost),才能使用 FedCM。
在 Android 裝置上對 Chrome 的程式碼進行偵錯
在本機設定並執行伺服器,對 FedCM 程式碼進行偵錯。您可以在使用具備通訊埠轉送功能的 USB 傳輸線連線的 Android 裝置上,在 Chrome 中存取這個伺服器。
您可以按照遠端對 Android 裝置進行偵錯的操作說明,在電腦上使用開發人員工具為 Android 上的 Chrome 偵錯。
在 Chrome 中封鎖第三方 Cookie
![將 Chrome 設為封鎖,模擬逐步淘汰第三方 Cookie](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/simulate-third-party-cook-8416bea1ab2b.png?authuser=6&hl=zh-tw)
您可以在 Chrome 實際強制執行 FedCM 之前,先測試 FedCM 的運作方式。
如要封鎖第三方 Cookie,請使用無痕模式,或是在電腦版設定中前往 chrome://settings/cookies
選擇「封鎖第三方 Cookie」,或是在行動裝置上依序前往「設定」>「網站設定」>「Cookie」,選擇「封鎖第三方 Cookie」。
使用 FedCM API
如要與 FedCM 整合,請建立已知檔案、設定檔和端點:用於帳戶清單、宣告核發和選擇用戶端中繼資料。
接著,FedCM 會公開 JavaScript API,讓 RP 能夠使用 IdP 登入。
建立知名檔案
為避免追蹤程式濫用 API,必須透過 IdP 的 eTLD+1 的 /.well-known/web-identity
提供已知檔案。
舉例來說,如果 IdP 端點是在 https://accounts.idp.example/
底下提供,就必須在 https://idp.example/.well-known/web-identity
和 IdP 設定檔中提供已知檔案。以下是知名的檔案內容範例:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
JSON 檔案必須包含 provider_urls
屬性,以及包含 IdP 設定檔網址的陣列,才能依 RP 將 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-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"
其中之一。
![如何將品牌宣傳元素套用至 FedCM 對話方塊](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/RZwmFnyJChjlki8QsnBB.png?authuser=6&hl=zh-tw)
以下是 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 端點](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/idp-endpoints-a67327f46da51.png?authuser=6&hl=zh-tw)
帳戶端點
IdP 的帳戶端點會傳回使用者目前在 IdP 上登入的帳戶清單。如果 IdP 支援多個帳戶,這個端點就會傳回所有已登入的帳戶。
瀏覽器傳送帶有 SameSite=None
的 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 的用戶端中繼資料端點會傳回依賴方的中繼資料,例如 RP 的隱私權政策和服務條款。RP 應事先提供 IdP 的隱私權政策和服務條款連結。如果使用者尚未透過 IdP 註冊 RP,就會在登入對話方塊中顯示這些連結。
瀏覽器會使用 client_id
navigator.credentials.get
在沒有 Cookie 的情況下傳送 GET
要求。例如:
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 (非必要) |
受限方隱私權政策網址。 |
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 網站時,瀏覽器會向這個端點傳送含有 SameSite=None
的 POST
要求,以及 POST
內容類型至 application/x-www-form-urlencoded
,並提供以下資訊:
屬性 | 說明 |
---|---|
client_id (必填) |
RP 的用戶端 ID。 |
account_id (必填) |
登入使用者的專屬 ID。 |
nonce (非必要) |
要求 Nonce,由 RP 提供。 |
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
收到要求後,伺服器應會進行以下操作:
- 使用 CORS (跨源資源共享) 回應要求。
- 確認要求包含
Sec-Fetch-Dest: webidentity
HTTP 標頭。 - 比對
Origin
標頭與 RP 來源,由client_id
決定。 如果不相符,則拒絕。 - 將
account_id
與已登入帳戶的 ID 進行比對。如果兩者不相符,請拒絕。 - 以權杖回應。如果要求遭拒,請以錯誤回應回應。
符記是由 IdP 核發,但通常都會使用帳戶 ID、用戶端 ID、核發者來源 nonce
等資訊簽署,以便 RP 驗證權杖的真實性。
瀏覽器預期 JSON 回應應包含下列屬性:
屬性 | 說明 |
---|---|
token (必填) |
權杖是包含驗證聲明的字串。 |
{
"token": "***********"
}
傳回的權杖會由瀏覽器傳遞至 RP,以便 RP 能驗證驗證。
傳回錯誤回應
id_assertion_endpoint
也可以傳回「錯誤」回應,其中包含兩個選用欄位:
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()
後,瀏覽器會向這個中斷連線的端點傳送含有 SameSite=None
的 Cookie 和內容類型為 application/x-www-form-urlencoded
的跨來源 POST
要求,並提供以下資訊:
屬性 | 說明 |
---|---|
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
標頭與 RP 來源,由client_id
決定。 如果不相符,則拒絕。 - 將
account_hint
與已登入帳戶的 ID 進行比對。 - 中斷使用者帳戶與 RP 的連線。
- 以 JSON 格式回應瀏覽器,指出已識別的使用者帳戶資訊。
回應 JSON 酬載的範例如下所示:
{
"account_id": "account456"
}
如果 IdP 希望瀏覽器取消連結所有與 RP 相關聯的帳戶,請傳送不符合任何帳戶 ID 的字串,例如 "*"
。
登入網址
透過 Login Status API,IdP 必須通知使用者瀏覽器的登入狀態。不過,狀態可能不同步,例如工作階段到期時。在此情況下,瀏覽器可以動態讓使用者透過在 idp 設定檔的 login_url
中指定的登入網頁網址登入 IdP。
FedCM 對話方塊會顯示訊息建議登入,如下圖所示。
![A](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-120-1.png?authuser=6&hl=zh-tw)
使用者按一下「Continue」按鈕後,瀏覽器會開啟 IdP 登入頁面的彈出式視窗。
![自有自營頻道](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-120-2.png?authuser=6&hl=zh-tw)
對話方塊是包含第一方 Cookie 的一般瀏覽器視窗。無論對話方塊的內容為何,只要是由 IdP 進行,且沒有任何視窗控點都無法對 RP 頁面發出跨源通訊要求。使用者登入後,IdP 應:
- 傳送
Set-Login: logged-in
標頭或呼叫navigator.login.setStatus("logged-in")
API,通知瀏覽器使用者已登入。 - 呼叫
IdentityProvider.close()
即可關閉對話方塊。
![A](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm.gif?authuser=6&hl=zh-tw)
通知瀏覽器使用者在識別資訊提供者的登入狀態
Login Status API 是一種網站,可將網站 (特別是 IdP) 告知瀏覽器使用者在 IdP 上的登入狀態。透過這個 API,瀏覽器可減少對 IdP 不必要的要求,並降低潛在的時間攻擊。
IdP 可以傳送 HTTP 標頭,或是在使用者登入 IdP 或從其所有 IdP 帳戶中登出時呼叫 JavaScript API,藉此向瀏覽器告知使用者的登入狀態。瀏覽器會為每個 IdP (透過設定網址識別) 保留一個三狀態變數,代表登入狀態,以及可能的值:logged-in
、logged-out
和 unknown
。預設狀態為 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
時,如果未向 IdP 的帳戶端點發出要求,呼叫 FedCM 時就會失敗,而且不會顯示相關通知。
已設定 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,瀏覽器就不會顯示揭露文字「For continue with ...."」。
註冊狀態取決於是否已滿足下列條件:
- 如果
approved_clients
包含 RP 的clientId
。 - 如果瀏覽器記住使用者已註冊 RP。
當 RP 呼叫 navigator.credentials.get()
時,下列活動會發生:
- 瀏覽器傳送要求並擷取數個文件:
- 瀏覽器會顯示使用者可用來登入的帳戶清單,以及服務條款和隱私權政策 (如有)。
- 使用者選擇要登入的帳戶後,系統會將對 ID 斷言端點的要求傳送至 IdP,以擷取憑證。
- RP 可以驗證符記來驗證使用者。
![登入 API 呼叫](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/login-api-call-a55fdb8f753e8.png?authuser=6&hl=zh-tw)
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 帳戶。使用者輕觸提示時,系統會開啟彈出式視窗,其中包含設定檔中指定的登入網址。隨後連結會附上登入提示和網域提示查詢參數。
網域提示 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 相符,便會顯示登入提示範例。](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-123.jpg?authuser=6&hl=zh-tw)
domainHint
時的登入提示範例。顯示錯誤訊息
有時候,IdP 可能會基於正當理由 (例如用戶端未經授權,) 無法核發權杖。如果 IdP 傳回「error」回應,RP 就可以擷取該回應,Chrome 還會透過顯示 IdP 提供錯誤資訊的瀏覽器 UI 來通知使用者。
![A](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-120-4.png?authuser=6&hl=zh-tw)
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 登入對話方塊中的「Continue as...」按鈕,藉此建立帳戶或登入 RP 網站。
雖然在使用者建立聯合帳戶防止追蹤 (FedCM 的主要目標之一) 之前,明確的使用者體驗才顯得合理,但使用者一旦授予權限,允許 RP 與 IdP 之間進行通訊,就顯得較為麻煩:使用者授予 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'
:一律要求中介服務才可繼續操作,例如按一下使用者介面上的「繼續」按鈕。如果使用者每次需要進行驗證時,都會明確授予權限,請選擇這個選項。'silent'
:如果可能,自動重新驗證;如果沒有,則在不要求中介服務的情況下失敗。建議您在專屬登入頁面以外的其他頁面中選擇此選項,例如運送網站上的商品頁面或新聞網站的文章頁面。'conditional'
:用於 WebAuthn,且目前不適用於 FedCM。
在此呼叫中,系統會在下列情況下自動重新驗證:
- 可以使用 FedCM。例如,使用者尚未全域停用 FedCM,或設定中未針對 RP 停用 FedCM。
- 使用者只使用一個具備 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 應呼叫 navigator.credentials.preventSilentAccess()
,明確要求瀏覽器在使用者明確登出 RP 時 (例如點選登出按鈕) 停用自動重新驗證。
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 不一定與帳戶清單端點所提供的帳戶 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。方法是將 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")
如要進一步瞭解權限政策的運作方式,請參閱使用權限政策控管瀏覽器功能一文。