Tìm hiểu cách sử dụng FedCM để liên kết danh tính bảo đảm quyền riêng tư.
FedCM (Quản lý thông tin xác thực liên kết) là một phương pháp bảo đảm quyền riêng tư cho các dịch vụ nhận dạng được liên kết (chẳng hạn như "Đăng nhập bằng..."), trong đó người dùng có thể đăng nhập vào trang web mà không cần chia sẻ thông tin cá nhân của họ với dịch vụ nhận dạng hoặc trang web.
Để tìm hiểu thêm về trường hợp sử dụng, luồng người dùng và lộ trình API của FedCM, hãy tham khảo phần giới thiệu về API FedCM.
Môi trường phát triển FedCM
Bạn cần có một ngữ cảnh bảo mật (HTTPS hoặc localhost) trên cả IdP và RP trong Chrome để sử dụng FedCM.
Gỡ lỗi mã trên Chrome trên Android
Thiết lập và chạy một máy chủ cục bộ để gỡ lỗi mã FedCM của bạn. Bạn có thể truy cập vào máy chủ này trong Chrome trên thiết bị Android được kết nối bằng cáp USB có tính năng chuyển tiếp cổng.
Bạn có thể sử dụng Công cụ cho nhà phát triển trên máy tính để gỡ lỗi Chrome trên Android bằng cách làm theo hướng dẫn tại phần Gỡ lỗi từ xa trên thiết bị Android.
Chặn cookie của bên thứ ba trên Chrome
![Mô phỏng hoạt động loại bỏ cookie của bên thứ ba bằng cách định cấu hình Chrome để chặn các cookie đó](https://developers.google.cn/static/privacy-sandbox/assets/images/simulate-third-party-cook-8416bea1ab2b.png?authuser=5&hl=vi)
Bạn có thể kiểm thử cách FedCM hoạt động mà không cần cookie của bên thứ ba trên Chrome trước khi FedCM thực sự được thực thi.
Để chặn cookie của bên thứ ba, hãy sử dụng Chế độ ẩn danh hoặc chọn "Chặn cookie của bên thứ ba" trong phần cài đặt dành cho máy tính tại chrome://settings/cookies
hoặc trên thiết bị di động bằng cách chuyển đến phần Cài đặt > Cài đặt trang web > Cookie.
Sử dụng API FedCM
Bạn tích hợp với FedCM bằng cách tạo một tệp phổ biến, tệp cấu hình và điểm cuối cho danh sách tài khoản, phát hành xác nhận và siêu dữ liệu ứng dụng (không bắt buộc).
Từ đó, FedCM sẽ hiển thị các API JavaScript mà RP có thể dùng để đăng nhập bằng IdP.
Tạo một tệp phổ biến
Để ngăn các trình theo dõi lạm dụng API, một tệp phổ biến phải được phân phát từ /.well-known/web-identity
của eTLD+1 của IdP.
Ví dụ: nếu các điểm cuối của IdP được phân phát trong https://accounts.idp.example/
, thì các điểm cuối đó phải phân phát một tệp phổ biến tại https://idp.example/.well-known/web-identity
cũng như một tệp cấu hình IdP. Dưới đây là một ví dụ về nội dung tệp phổ biến:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
Tệp JSON phải chứa thuộc tính provider_urls
với một mảng URL tệp cấu hình IdP có thể được chỉ định là một phần đường dẫn của configURL
trong navigator.credentials.get
bởi RP. Số lượng chuỗi URL trong mảng chỉ giới hạn là 1, nhưng sau này có thể thay đổi theo ý kiến phản hồi của bạn.
Tạo một tệp cấu hình IdP và điểm cuối
Tệp cấu hình IdP cung cấp một danh sách các điểm cuối bắt buộc cho trình duyệt. IdP sẽ lưu trữ tệp cấu hình này cũng như các điểm cuối và URL bắt buộc. Tất cả phản hồi JSON phải được phân phát với loại nội dung application/json
.
URL của tệp cấu hình được xác định bằng các giá trị cung cấp cho lệnh gọi navigator.credentials.get
được thực thi trên một RP.
const credential = await navigator.credentials.get({
identity: {
context: 'signup',
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Chỉ định một URL đầy đủ của vị trí tệp cấu hình IdP dưới dạng configURL
. Khi navigator.credentials.get()
được gọi trên RP, trình duyệt sẽ tìm nạp tệp cấu hình với yêu cầu GET
không có tiêu đề Origin
hoặc tiêu đề Referer
. Yêu cầu không có cookie và không tuân theo lệnh chuyển hướng.
Điều này ngăn chặn một cách hiệu quả việc IdP biết được ai đã đưa ra yêu cầu và
RP nào đang cố gắng kết nối. Ví dụ:
GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity
Trình duyệt dự kiến sẽ nhận được phản hồi JSON từ IdP, bao gồm các thuộc tính sau:
Tài sản | Nội dung mô tả |
---|---|
accounts_endpoint (bắt buộc) |
URL cho điểm cuối của tài khoản. |
client_metadata_endpoint (không bắt buộc) |
URL cho điểm cuối siêu dữ liệu ứng dụng. |
id_assertion_endpoint (bắt buộc) |
URL cho điểm cuối xác nhận mã nhận dạng. |
disconnect (không bắt buộc) |
URL cho điểm cuối ngắt kết nối. |
login_url (bắt buộc) |
URL trang đăng nhập để người dùng đăng nhập vào IdP. |
branding (không bắt buộc) |
Đối tượng chứa nhiều tuỳ chọn xây dựng thương hiệu. |
branding.background_color (không bắt buộc) |
Tuỳ chọn xây dựng thương hiệu đặt màu nền cho nút "Tiếp tục dưới dạng...". Sử dụng cú pháp CSS có liên quan, cụ thể là hex-color , hsl() , rgb() hoặc named-color . |
branding.color (không bắt buộc) |
Tuỳ chọn xây dựng thương hiệu giúp đặt màu văn bản cho nút "Tiếp tục dưới dạng...". Sử dụng cú pháp CSS có liên quan, cụ thể là hex-color , hsl() , rgb() hoặc named-color . |
branding.icons (không bắt buộc) |
Tuỳ chọn xây dựng thương hiệu giúp đặt đối tượng biểu tượng, xuất hiện trong hộp thoại đăng nhập. Đối tượng biểu tượng là một mảng có hai tham số:
|
RP có thể sửa đổi chuỗi trong giao diện người dùng của hộp thoại FedCM thông qua giá trị identity.context
cho navigator.credentials.get()
để phù hợp với ngữ cảnh xác thực
được xác định trước. Thuộc tính không bắt buộc có thể là một trong các giá trị "signin"
(mặc định), "signup"
, "use"
hoặc "continue"
.
![Cách áp dụng thương hiệu cho hộp thoại FedCM](https://developers.google.cn/static/privacy-sandbox/assets/images/RZwmFnyJChjlki8QsnBB.png?authuser=5&hl=vi)
Dưới đây là ví dụ về nội dung phản hồi của 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
}]
}
}
Sau khi tìm nạp tệp cấu hình, trình duyệt sẽ gửi các yêu cầu tiếp theo đến các điểm cuối IdP:
![Điểm cuối IdP](https://developers.google.cn/static/privacy-sandbox/assets/images/idp-endpoints-a67327f46da51.png?authuser=5&hl=vi)
Điểm cuối của tài khoản
Điểm cuối tài khoản của IdP sẽ trả về danh sách các tài khoản mà người dùng hiện đang đăng nhập trên IdP. Nếu IdP hỗ trợ nhiều tài khoản, điểm cuối này sẽ trả về tất cả các tài khoản đã đăng nhập.
Trình duyệt gửi yêu cầu GET
chứa cookie có SameSite=None
, nhưng không có tham số client_id
, tiêu đề Origin
hoặc Referer
. Việc này giúp ngăn IdP biết được người dùng đang muốn đăng nhập vào bên bị hạn chế nào. Ví dụ:
GET /accounts.php HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
Khi nhận được yêu cầu, máy chủ nên:
- Xác minh rằng yêu cầu chứa tiêu đề HTTP
Sec-Fetch-Dest: webidentity
. - So khớp cookie phiên với mã nhận dạng của các tài khoản đã đăng nhập.
- Trả lời kèm theo danh sách tài khoản.
Trình duyệt dự kiến phản hồi JSON bao gồm thuộc tính accounts
với một mảng thông tin tài khoản có các thuộc tính sau:
Tài sản | Nội dung mô tả |
---|---|
id (bắt buộc) |
Mã nhận dạng duy nhất của người dùng. |
name (bắt buộc) |
Họ và tên của người dùng. |
email (bắt buộc) |
Địa chỉ email của người dùng. |
given_name (không bắt buộc) |
Tên của người dùng. |
picture (không bắt buộc) |
URL của hình đại diện của người dùng. |
approved_clients (không bắt buộc) |
Một mảng gồm các mã ứng dụng của bên bị hạn chế mà người dùng đã đăng ký. |
login_hints (không bắt buộc) |
Một mảng gồm tất cả các loại bộ lọc có thể có mà IdP hỗ trợ để chỉ định một tài khoản. RP có thể gọi navigator.credentials.get() bằng thuộc tính loginHint để hiển thị có chọn lọc tài khoản được chỉ định. |
domain_hints (không bắt buộc) |
Một mảng gồm tất cả các miền mà tài khoản được liên kết. Bên bị hạn chế có thể gọi navigator.credentials.get() bằng thuộc tính domainHint để lọc các tài khoản. |
Ví dụ về nội dung phản hồi:
{
"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"]
}]
}
Nếu người dùng chưa đăng nhập, hãy phản hồi bằng HTTP 401 (Không được phép).
Danh sách tài khoản được trả về sẽ được trình duyệt sử dụng và sẽ không có sẵn cho bên bị hạn chế.
Điểm cuối siêu dữ liệu của ứng dụng
Điểm cuối siêu dữ liệu ứng dụng của IdP sẽ trả về siêu dữ liệu của bên đáng tin cậy, chẳng hạn như chính sách quyền riêng tư và điều khoản dịch vụ của RP. Bên bị hạn chế phải cung cấp trước các đường liên kết đến chính sách quyền riêng tư và điều khoản dịch vụ của họ cho IdP. Các đường liên kết này sẽ xuất hiện trong hộp thoại đăng nhập khi người dùng chưa đăng ký bằng IdP trên RP.
Trình duyệt gửi yêu cầu GET
bằng client_id
navigator.credentials.get
mà không cần cookie. Ví dụ:
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
Khi nhận được yêu cầu, máy chủ nên:
- Xác định RP cho
client_id
. - Phản hồi bằng siêu dữ liệu ứng dụng.
Các thuộc tính của điểm cuối siêu dữ liệu ứng dụng bao gồm:
Tài sản | Nội dung mô tả |
---|---|
privacy_policy_url (không bắt buộc) |
URL chính sách quyền riêng tư của bên bị hạn chế. |
terms_of_service_url (không bắt buộc) |
URL của điều khoản dịch vụ về bên bị hạn chế. |
Trình duyệt dự kiến sẽ nhận được phản hồi JSON từ điểm cuối:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html",
}
Siêu dữ liệu ứng dụng được trả về sẽ được trình duyệt sử dụng và sẽ không có sẵn cho bên bị hạn chế.
Điểm cuối xác nhận mã nhận dạng
Điểm cuối xác nhận mã nhận dạng của IdP sẽ trả về câu nhận định cho người dùng đã đăng nhập của họ.
Khi người dùng đăng nhập vào một trang web của bên bị hạn chế bằng cách dùng navigator.credentials.get()
gọi, trình duyệt sẽ gửi một POST
yêu cầu kèm cookie có SameSite=None
và content-type application/x-www-form-urlencoded
tới điểm cuối
này kèm theo thông tin sau:
Tài sản | Nội dung mô tả |
---|---|
client_id (bắt buộc) |
Mã nhận dạng khách hàng của bên bị hạn chế. |
account_id (bắt buộc) |
Mã nhận dạng duy nhất của người dùng đăng nhập. |
nonce (không bắt buộc) |
Số chỉ dùng một lần yêu cầu do bên bị hạn chế cung cấp. |
disclosure_text_shown |
Kết quả trong một chuỗi "true" hoặc "false" (thay vì boolean). Kết quả sẽ là "false" nếu văn bản công bố không xuất hiện. Điều này xảy ra khi mã ứng dụng khách của bên bị hạn chế được đưa vào danh sách thuộc tính approved_clients của phản hồi từ điểm cuối của tài khoản hoặc nếu trình duyệt đã nhận thấy thời điểm đăng ký trong quá khứ mà không có approved_clients . |
is_auto_selected |
Nếu tự động xác thực lại được thực hiện trên RP, thì is_auto_selected sẽ cho biết "true" . Nếu không, "false" . Điều này hữu ích để hỗ trợ thêm các tính năng liên quan đến bảo mật. Ví dụ: một số người dùng có thể thích cấp bảo mật cao hơn, do đó yêu cầu phải có sự dàn xếp rõ ràng của người dùng trong quy trình xác thực. Nếu một IdP nhận được yêu cầu mã thông báo mà không cần tính năng dàn xếp như vậy, họ có thể xử lý yêu cầu theo cách khác. Ví dụ: trả về một mã lỗi để RP có thể gọi lại API FedCM bằng mediation: required . |
Ví dụ về tiêu đề 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
Khi nhận được yêu cầu, máy chủ nên:
- Phản hồi yêu cầu bằng tính năng CORS (Chia sẻ tài nguyên trên nhiều nguồn gốc).
- Xác minh rằng yêu cầu chứa tiêu đề HTTP
Sec-Fetch-Dest: webidentity
. - So khớp tiêu đề
Origin
với nguồn gốc RP doclient_id
xác định. Từ chối nếu các chi tiết đó không khớp. - So khớp
account_id
với mã của tài khoản đã đăng nhập. Từ chối nếu chúng không khớp. - Hãy phản hồi bằng mã thông báo. Nếu yêu cầu bị từ chối, hãy phản hồi bằng phản hồi lỗi.
Cách thức phát hành mã thông báo tuỳ thuộc vào IdP, nhưng nhìn chung, mã được ký bằng các thông tin như mã tài khoản, mã ứng dụng khách, nguồn gốc của nhà phát hành, nonce
để RP có thể xác minh mã đó là thật.
Trình duyệt muốn nhận được phản hồi JSON bao gồm thuộc tính sau:
Tài sản | Nội dung mô tả |
---|---|
token (bắt buộc) |
Mã thông báo là một chuỗi chứa các thông báo xác nhận quyền sở hữu về hoạt động xác thực. |
{
"token": "***********"
}
Mã thông báo trả về sẽ được trình duyệt chuyển đến RP để RP có thể xác thực quy trình xác thực.
Trả về phản hồi lỗi
id_assertion_endpoint
cũng có thể trả về phản hồi "lỗi", trong đó có hai trường không bắt buộc:
code
: IdP có thể chọn một trong các lỗi đã biết từ danh sách lỗi được chỉ định OAuth 2.0 (invalid_request
,unauthorized_client
,access_denied
,server_error
vàtemporarily_unavailable
) hoặc sử dụng chuỗi tuỳ ý. Nếu lỗi sau, Chrome sẽ hiển thị giao diện người dùng lỗi với thông báo lỗi chung rồi chuyển mã đó đến bên bị hạn chế.url
: Mã này xác định một trang web mà con người có thể đọc được, kèm theo thông tin về lỗi để cung cấp thêm thông tin về lỗi đó cho người dùng. Trường này hữu ích cho người dùng vì các trình duyệt không thể cung cấp thông báo lỗi nhiều định dạng trong giao diện người dùng gốc. Ví dụ: đường liên kết cho các bước tiếp theo, thông tin liên hệ của dịch vụ khách hàng, v.v. Nếu muốn tìm hiểu thêm về thông tin chi tiết về lỗi và cách khắc phục, người dùng có thể truy cập trang được cung cấp từ giao diện người dùng của trình duyệt để biết thêm thông tin. URL này phải thuộc cùng một trang web với IdPconfigURL
.
// id_assertion_endpoint response
{
"error" : {
"code": "access_denied",
"url" : "https://idp.example/error?type=access_denied"
}
}
Ngắt kết nối điểm cuối
Bằng cách gọi IdentityCredential.disconnect()
, trình duyệt sẽ gửi yêu cầu POST
trên nhiều nguồn gốc có cookie có SameSite=None
và loại nội dung application/x-www-form-urlencoded
đến điểm cuối ngắt kết nối này kèm theo thông tin sau:
Tài sản | Nội dung mô tả |
---|---|
account_hint |
Gợi ý cho tài khoản IdP.. |
client_id |
Mã nhận dạng khách hàng của bên bị hạn chế. |
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
Khi nhận được yêu cầu, máy chủ nên:
- Phản hồi yêu cầu bằng tính năng CORS (Chia sẻ tài nguyên trên nhiều nguồn gốc).
- Xác minh rằng yêu cầu chứa tiêu đề HTTP
Sec-Fetch-Dest: webidentity
. - So khớp tiêu đề
Origin
với nguồn gốc RP doclient_id
xác định. Từ chối nếu các chi tiết đó không khớp. - So khớp
account_hint
với mã nhận dạng của các tài khoản đã đăng nhập. - Ngắt kết nối tài khoản người dùng khỏi bên bị hạn chế.
- Phản hồi trình duyệt bằng thông tin tài khoản người dùng đã xác định ở định dạng JSON.
Ví dụ về tải trọng JSON phản hồi có dạng như sau:
{
"account_id": "account456"
}
Thay vào đó, nếu IdP muốn trình duyệt ngắt kết nối mọi tài khoản liên kết với RP đó, hãy chuyển một chuỗi không khớp với bất kỳ mã tài khoản nào, ví dụ: "*"
.
URL đăng nhập
Với API Trạng thái đăng nhập, IdP phải thông báo trạng thái đăng nhập của người dùng cho trình duyệt. Tuy nhiên, trạng thái có thể không đồng bộ, chẳng hạn như khi phiên hết hạn. Trong trường hợp như vậy, trình duyệt có thể cho phép người dùng tự động đăng nhập vào IdP thông qua URL của trang đăng nhập được chỉ định bằng login_url
của tệp cấu hình idp.
Hộp thoại FedCM hiển thị thông báo gợi ý việc đăng nhập, như trong hình sau.
![Đáp](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-120-1.png?authuser=5&hl=vi)
Khi người dùng nhấp vào nút Continue (Tiếp tục), trình duyệt sẽ mở một cửa sổ bật lên cho trang đăng nhập của IdP.
![Một](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-120-2.png?authuser=5&hl=vi)
Hộp thoại là cửa sổ trình duyệt thông thường có cookie của bên thứ nhất. Mọi điều xảy ra trong hộp thoại đều tuỳ thuộc vào IdP và không có cửa sổ nào xuất hiện để gửi yêu cầu giao tiếp giữa nhiều nguồn gốc tới trang RP. Sau khi người dùng đăng nhập, IdP sẽ:
- Gửi tiêu đề
Set-Login: logged-in
hoặc gọi APInavigator.login.setStatus("logged-in")
để thông báo cho trình duyệt rằng người dùng đã đăng nhập. - Gọi
IdentityProvider.close()
để đóng hộp thoại này.
![Đáp](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm.gif?authuser=5&hl=vi)
Thông báo cho trình duyệt về trạng thái đăng nhập của người dùng trên nhà cung cấp danh tính
API trạng thái đăng nhập là một cơ chế trong đó trang web, đặc biệt là IdP, thông báo cho trình duyệt về trạng thái đăng nhập của người dùng trên IdP. Với API này, trình duyệt có thể giảm các yêu cầu không cần thiết đến IdP và giảm thiểu các cuộc tấn công có thể xảy ra về thời gian.
IdP có thể báo hiệu trạng thái đăng nhập của người dùng với trình duyệt bằng cách gửi tiêu đề HTTP hoặc bằng cách gọi API JavaScript khi người dùng đăng nhập trên IdP hoặc khi người dùng đã đăng xuất khỏi tất cả tài khoản IdP của họ. Đối với mỗi IdP (được xác định bằng URL cấu hình), trình duyệt sẽ lưu giữ một biến ba trạng thái biểu thị trạng thái đăng nhập với các giá trị có thể có logged-in
, logged-out
và unknown
. Trạng thái mặc định là unknown
.
Để cho biết rằng người dùng đã đăng nhập, hãy gửi tiêu đề HTTP Set-Login: logged-in
trong thành phần điều hướng cấp cao nhất hoặc yêu cầu tài nguyên phụ trên cùng trang web tại nguồn gốc IdP:
Set-Login: logged-in
Ngoài ra, bạn có thể gọi API JavaScript navigator.login.setStatus("logged-in")
từ nguồn gốc IdP trong thành phần điều hướng cấp cao nhất:
navigator.login.setStatus("logged-in")
Các lệnh gọi này sẽ ghi lại trạng thái đăng nhập của người dùng là logged-in
. Khi trạng thái đăng nhập của người dùng được đặt thành logged-in
, RP gọi FedCM sẽ gửi yêu cầu đến điểm cuối tài khoản của IdP và hiển thị các tài khoản có sẵn cho người dùng trong hộp thoại FedCM.
Để báo hiệu rằng người dùng đã đăng xuất khỏi tất cả tài khoản của họ, hãy gửi tiêu đề HTTP Set-Login:
logged-out
trong một thành phần điều hướng cấp cao nhất hoặc yêu cầu về tài nguyên phụ cùng trang web tại nguồn gốc của IdP:
Set-Login: logged-out
Ngoài ra, bạn có thể gọi API JavaScript navigator.login.setStatus("logged-out")
từ nguồn gốc IdP trong thành phần điều hướng cấp cao nhất:
navigator.login.setStatus("logged-out")
Các lệnh gọi này sẽ ghi lại trạng thái đăng nhập của người dùng là logged-out
. Khi trạng thái đăng nhập của người dùng là logged-out
, việc gọi FedCM sẽ tự động không thực hiện được mà không gửi yêu cầu đến điểm cuối của các tài khoản của IdP.
Trạng thái unknown
được đặt trước khi IdP gửi tín hiệu bằng API trạng thái đăng nhập. Chúng tôi giới thiệu Unknown
để chuyển đổi tốt hơn vì người dùng có thể đã đăng nhập vào IdP khi API này được vận chuyển. IdP có thể không có cơ hội báo hiệu điều này cho trình duyệt vào thời điểm FedCM được gọi lần đầu tiên. Trong trường hợp này, Chrome sẽ gửi yêu cầu đến điểm cuối tài khoản của IdP và cập nhật trạng thái dựa trên phản hồi từ điểm cuối của tài khoản:
- Nếu điểm cuối trả về danh sách các tài khoản đang hoạt động, hãy cập nhật trạng thái thành
logged-in
và mở hộp thoại FedCM để hiển thị các tài khoản đó. - Nếu điểm cuối không trả về tài khoản nào, hãy cập nhật trạng thái thành
logged-out
và không thực hiện được lệnh gọi FedCM.
Cho phép người dùng đăng nhập thông qua quy trình đăng nhập động
Mặc dù IdP liên tục thông báo trạng thái đăng nhập của người dùng vào trình duyệt, nhưng có thể trạng thái đăng nhập đó không đồng bộ, chẳng hạn như khi phiên hết hạn. Trình duyệt cố gắng gửi yêu cầu đã xác thực đến điểm cuối của tài khoản khi trạng thái đăng nhập là logged-in
, nhưng máy chủ không trả về tài khoản nào vì phiên không còn nữa. Trong trường hợp như vậy, trình duyệt có thể cho phép người dùng tự động đăng nhập vào IdP thông qua cửa sổ bật lên.
Đăng nhập vào bên đáng tin cậy thông qua nhà cung cấp danh tính
Sau khi có cấu hình và điểm cuối của IdP, RP có thể gọi navigator.credentials.get()
để yêu cầu cho phép người dùng đăng nhập vào RP bằng IdP.
Trước khi gọi API, bạn cần xác nhận rằng [FedCM có sẵn trên trình duyệt của người dùng]. Để kiểm tra xem FedCM có thể sử dụng được hay không, hãy gói mã này quanh quá trình triển khai FedCM của bạn:
if ('IdentityCredential' in window) {
// If the feature is available, take action
}
Để yêu cầu cho phép người dùng đăng nhập vào IdP từ RP, hãy làm như sau:
const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Thuộc tính providers
nhận một mảng đối tượng IdentityProvider
có các thuộc tính sau:
Tài sản | Nội dung mô tả |
---|---|
configURL (bắt buộc) |
Đường dẫn đầy đủ của tệp cấu hình IdP. |
clientId (bắt buộc) |
Mã nhận dạng khách hàng của bên bị hạn chế do IdP cấp. |
nonce (không bắt buộc) |
Một chuỗi ngẫu nhiên để đảm bảo phản hồi được đưa ra cho yêu cầu cụ thể này. Ngăn chặn các cuộc tấn công phát lại. |
loginHint (không bắt buộc) |
Bằng cách chỉ định một trong các giá trị login_hints do điểm cuối của tài khoản cung cấp, hộp thoại FedCM sẽ hiển thị một cách có chọn lọc tài khoản được chỉ định. |
domainHint (không bắt buộc) |
Bằng cách chỉ định một trong các giá trị domain_hints do điểm cuối của tài khoản cung cấp, hộp thoại FedCM sẽ hiển thị một cách có chọn lọc tài khoản được chỉ định. |
Trình duyệt xử lý các trường hợp sử dụng đăng ký và đăng nhập theo cách khác nhau tuỳ thuộc vào sự tồn tại của approved_clients
trong phản hồi từ điểm cuối của danh sách tài khoản. Trình duyệt sẽ không hiển thị văn bản công bố "Để tiếp tục với ...." nếu người dùng đã đăng ký RP.
Trạng thái đăng ký được xác định dựa trên việc các điều kiện sau có được thực hiện hay không:
- Nếu
approved_clients
bao gồmclientId
của bên bị hạn chế. - Nếu trình duyệt nhớ rằng người dùng đã đăng ký bên bị hạn chế.
Khi RP gọi navigator.credentials.get()
, các hoạt động sau đây sẽ diễn ra:
- Trình duyệt gửi yêu cầu và tìm nạp một số tài liệu:
- Tệp phổ biến và tệp cấu hình IdP giúp khai báo các điểm cuối.
- Danh sách tài khoản.
- Không bắt buộc: URL dành cho chính sách quyền riêng tư và điều khoản dịch vụ của bên bị hạn chế được truy xuất từ điểm cuối siêu dữ liệu của ứng dụng.
- Trình duyệt sẽ hiển thị danh sách các tài khoản người dùng có thể dùng để đăng nhập, cũng như điều khoản dịch vụ và chính sách quyền riêng tư (nếu có).
- Sau khi người dùng chọn một tài khoản để đăng nhập, một yêu cầu tới điểm cuối xác nhận mã nhận dạng sẽ được gửi đến IdP để truy xuất một mã thông báo.
- RP có thể xác thực mã thông báo để xác thực người dùng.
![lệnh gọi API đăng nhập](https://developers.google.cn/static/privacy-sandbox/assets/images/login-api-call-a55fdb8f753e8.png?authuser=5&hl=vi)
RP dự kiến sẽ hỗ trợ các trình duyệt không hỗ trợ FedCM, do đó, người dùng có thể sử dụng quy trình đăng nhập hiện có, không phải FedCM. Cho đến khi cookie của bên thứ ba bị loại bỏ hoàn toàn, tình trạng này vẫn sẽ không có vấn đề gì.
Sau khi máy chủ RP xác thực mã thông báo, RP có thể đăng ký người dùng hoặc cho phép họ đăng nhập và bắt đầu một phiên mới.
API Gợi ý đăng nhập
Sau khi người dùng đăng nhập, đôi khi bên đáng tin cậy (RP) yêu cầu người dùng xác thực lại. Tuy nhiên, người dùng có thể không chắc chắn mình đang sử dụng tài khoản nào. Nếu bên bị hạn chế có thể chỉ định tài khoản cần đăng nhập, thì sẽ dễ dàng chọn tài khoản hơn cho người dùng.
Bên bị hạn chế có thể hiển thị có chọn lọc một tài khoản cụ thể bằng cách gọi navigator.credentials.get()
với thuộc tính loginHint
với một trong các giá trị login_hints
được tìm nạp từ điểm cuối của danh sách tài khoản, như trong mã mẫu sau:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "123",
nonce: nonce,
loginHint : "demo1@example.com"
}]
}
});
Khi không có tài khoản nào khớp với loginHint
, hộp thoại FedCM sẽ hiển thị lời nhắc đăng nhập, cho phép người dùng đăng nhập vào tài khoản IdP khớp với gợi ý do RP yêu cầu. Khi người dùng nhấn vào lời nhắc, một cửa sổ bật lên sẽ mở ra với URL đăng nhập được chỉ định trong tệp cấu hình. Sau đó, đường liên kết sẽ được thêm bằng gợi ý đăng nhập và tham số truy vấn gợi ý miền.
API Gợi ý miền
Có những trường hợp mà RP đã biết rằng chỉ những tài khoản liên kết với một miền nhất định mới được phép đăng nhập vào trang web. Điều này đặc biệt phổ biến trong các trường hợp của doanh nghiệp khi trang web bị giới hạn truy cập ở miền doanh nghiệp. Để mang lại trải nghiệm người dùng tốt hơn, API FedCM cho phép RP chỉ hiển thị những tài khoản có thể dùng để đăng nhập vào RP. Điều này giúp ngăn chặn các trường hợp người dùng cố gắng đăng nhập vào RP bằng một tài khoản bên ngoài miền của công ty và chỉ nhìn thấy thông báo lỗi sau đó (hoặc khoảng lặng khi đăng nhập không hoạt động) do không sử dụng đúng loại tài khoản.
RP có thể chỉ hiển thị một cách có chọn lọc những tài khoản trùng khớp bằng cách gọi navigator.credentials.get()
với thuộc tính domainHint
với một trong các giá trị domain_hints
được tìm nạp từ điểm cuối của danh sách tài khoản, như trong mã mẫu sau:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "abc",
nonce: nonce,
domainHint : "corp.example"
}]
}
});
Khi không có tài khoản nào khớp với domainHint
, hộp thoại FedCM sẽ hiển thị lời nhắc đăng nhập, cho phép người dùng đăng nhập vào tài khoản IdP khớp với gợi ý do RP yêu cầu. Khi người dùng nhấn vào lời nhắc, một cửa sổ bật lên sẽ mở ra với URL đăng nhập được chỉ định trong tệp cấu hình. Sau đó, đường liên kết sẽ được thêm bằng gợi ý đăng nhập và tham số truy vấn gợi ý miền.
![Ví dụ về lời nhắc đăng nhập khi không có tài khoản nào khớp với miềnHint.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-123.jpg?authuser=5&hl=vi)
domainHint
.Hiện thông báo lỗi
Đôi khi, IdP có thể không cấp mã được vì những lý do chính đáng, chẳng hạn như khi ứng dụng không được phép, máy chủ tạm thời không hoạt động. Nếu IdP trả về phản hồi "lỗi", RP có thể phát hiện lỗi đó, cũng như Chrome thông báo cho người dùng bằng cách hiển thị giao diện người dùng của trình duyệt kèm theo thông tin lỗi do IdP cung cấp.
![Đáp](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-120-4.png?authuser=5&hl=vi)
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;
}
Tự động xác thực lại người dùng sau lần xác thực ban đầu
Tính năng tự động xác thực lại FedCM ("tự động xác thực lại") có thể cho phép người dùng tự động xác thực lại khi họ quay lại sau lần xác thực ban đầu bằng FedCM. Quy trình "Xác thực ban đầu" ở đây có nghĩa là người dùng tạo tài khoản hoặc đăng nhập vào trang web của RP bằng cách nhấn vào nút "Continue as..." (Tiếp tục dưới dạng...) lần đầu tiên trên hộp thoại đăng nhập của FedCM trên cùng một phiên bản trình duyệt.
Mặc dù trải nghiệm người dùng rõ ràng là hợp lý trước khi người dùng tạo tài khoản liên kết để ngăn hoạt động theo dõi (đây là một trong những mục tiêu chính của FedCM), nhưng việc rườm rà một cách không cần thiết sau khi người dùng đã trải qua quy trình đó một lần: sau khi người dùng cấp quyền cho phép giao tiếp giữa RP và IdP, sẽ không có lợi ích về quyền riêng tư hoặc tính bảo mật nào khi thực thi một xác nhận rõ ràng khác của người dùng đối với những nội dung mà họ đã xác nhận trước đó.
Với tính năng tự động xác thực lại, trình duyệt sẽ thay đổi hành vi của mình tuỳ thuộc vào tuỳ chọn mà bạn chỉ định cho mediation
khi gọi navigator.credentials.get()
.
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
là một thuộc tính trong API Quản lý thông tin xác thực và hoạt động theo cách tương tự đối với PasswordCredential và FederatedCredential cũng như được PublicKeyCredential hỗ trợ một phần. Cơ sở lưu trú chấp nhận 4 giá trị sau:
'optional'
(mặc định): Tự động xác thực lại nếu có thể, yêu cầu dàn xếp nếu không. Bạn nên chọn tuỳ chọn này trên trang đăng nhập.'required'
: Luôn yêu cầu tiến hành dàn xếp, chẳng hạn như nhấp vào nút "Tiếp tục" trên giao diện người dùng. Chọn tuỳ chọn này nếu người dùng của bạn dự kiến sẽ cấp quyền rõ ràng mỗi khi cần được xác thực.'silent'
: Tự động xác thực lại nếu có thể, tự động không thành công mà không cần yêu cầu dàn xếp nếu không. Bạn nên chọn tuỳ chọn này trên các trang không phải trang đăng nhập chuyên dụng nhưng là nơi bạn muốn duy trì trạng thái đăng nhập của người dùng. Ví dụ: một trang về mặt hàng trên trang web về vận chuyển hoặc trang bài viết trên trang web tin tức.'conditional'
: Dùng cho WebAuthn và hiện không hỗ trợ FedCM.
Với lệnh gọi này, quá trình tự động xác thực lại diễn ra trong các điều kiện sau:
- FedCM có thể sử dụng được. Ví dụ: người dùng chưa tắt FedCM trên toàn cầu hoặc RP trong phần cài đặt.
- Người dùng chỉ sử dụng một tài khoản có API FedCM để đăng nhập vào trang web trên trình duyệt này.
- Người dùng đăng nhập vào IdP bằng tài khoản đó.
- Quá trình tự động xác thực đã không xảy ra trong vòng 10 phút qua.
- RP chưa gọi
navigator.credentials.preventSilentAccess()
sau lần đăng nhập trước đó.
Khi các điều kiện này được đáp ứng, việc thử tự động xác thực lại người dùng sẽ bắt đầu ngay khi navigator.credentials.get()
của FedCM được gọi.
Khi mediation: optional
, tính năng tự động xác thực lại có thể không hoạt động vì những lý do mà chỉ trình duyệt mới biết; RP có thể kiểm tra xem tính năng tự động xác thực lại có được thực hiện hay không bằng cách kiểm tra thuộc tính isAutoSelected
.
Điều này rất hữu ích để đánh giá hiệu suất của API và cải thiện trải nghiệm người dùng cho phù hợp.
Ngoài ra, khi không có tính năng này, người dùng có thể được nhắc đăng nhập bằng tính năng dàn xếp người dùng rõ ràng, đây là một quy trình với mediation: required
.
Thực thi quy trình dàn xếp bằng preventSilentAccess()
Việc tự động xác thực lại người dùng ngay sau khi họ đăng xuất sẽ không mang lại trải nghiệm tốt cho người dùng. Đó là lý do FedCM có khoảng thời gian yên tĩnh 10 phút sau khi tự động xác thực lại để ngăn chặn hành vi này. Điều này có nghĩa là quá trình tự động xác thực lại diễn ra tối đa một lần 10 phút một lần trừ phi người dùng đăng nhập lại trong vòng 10 phút. RP nên gọi navigator.credentials.preventSilentAccess()
để yêu cầu trình duyệt tắt tính năng tự động xác thực lại một cách rõ ràng khi người dùng đăng xuất khỏi RP một cách rõ ràng, chẳng hạn như bằng cách nhấp vào nút đăng xuất.
function signout() {
navigator.credentials.preventSilentAccess();
location.href = '/signout';
}
Người dùng có thể chọn không sử dụng tính năng tự động xác thực lại trong phần cài đặt
Người dùng có thể chọn không sử dụng tính năng tự động xác thực lại trong trình đơn cài đặt:
- Trên Chrome dành cho máy tính, hãy chuyển đến
chrome://password-manager/settings
> Đăng nhập tự động. - Trên Android Chrome, hãy mở Cài đặt > Trình quản lý mật khẩu > Nhấn vào một bánh răng ở góc trên cùng bên phải > Tự động đăng nhập.
Khi tắt nút bật/tắt, người dùng có thể chọn không sử dụng hành vi tự động xác thực lại. Chế độ cài đặt này được lưu trữ và đồng bộ hoá trên các thiết bị nếu người dùng đăng nhập vào Tài khoản Google trên phiên bản Chrome và bật tính năng đồng bộ hoá.
Ngắt kết nối IdP khỏi RP
Nếu người dùng trước đây đã đăng nhập vào RP bằng IdP thông qua FedCM, thì mối quan hệ sẽ được trình duyệt ghi nhớ cục bộ dưới dạng danh sách các tài khoản đã kết nối. RP có thể bắt đầu ngắt kết nối bằng cách gọi hàm IdentityCredential.disconnect()
. Hàm này có thể được gọi từ khung RP cấp cao nhất. RP cần truyền configURL
, clientId
mà ứng dụng này sử dụng trong IdP và accountHint
để ngắt kết nối IdP. Gợi ý về tài khoản có thể là một chuỗi tuỳ ý miễn là điểm cuối ngắt kết nối có thể xác định tài khoản (ví dụ: địa chỉ email hoặc mã nhận dạng người dùng không nhất thiết phải khớp với mã tài khoản mà điểm cuối trong danh sách tài khoản đã cung cấp):
// 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()
trả về một Promise
. Lời hứa này có thể gửi một trường hợp ngoại lệ vì những lý do sau:
- Người dùng chưa đăng nhập vào RP bằng IdP thông qua FedCM.
- API được gọi từ bên trong iframe mà không có chính sách về quyền của FedCM.
- configURL không hợp lệ hoặc thiếu điểm cuối ngắt kết nối.
- Không kiểm tra được Chính sách bảo mật nội dung (CSP).
- Có một yêu cầu ngắt kết nối đang chờ xử lý.
- Người dùng đã tắt FedCM trong phần cài đặt của trình duyệt.
Khi điểm cuối ngắt kết nối của IdP trả về một phản hồi, RP và IdP sẽ bị ngắt kết nối trên trình duyệt và lời hứa sẽ được giải quyết. Mã của các tài khoản đã ngắt kết nối được chỉ định trong phản hồi từ điểm cuối ngắt kết nối.
Gọi FedCM từ bên trong iframe trên nhiều nguồn gốc
Bạn có thể gọi FedCM từ bên trong iframe trên nhiều nguồn gốc bằng cách sử dụng chính sách quyền identity-credentials-get
nếu khung chính cho phép. Để làm như vậy, hãy thêm thuộc tính allow="identity-credentials-get"
vào thẻ iframe như sau:
<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>
Bạn có thể xem ví dụ thực tế về tính năng này trong ví dụ.
Nếu khung gốc muốn hạn chế các nguồn gốc để gọi FedCM, hãy gửi tiêu đề Permissions-Policy
kèm theo danh sách các nguồn gốc được phép.
Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")
Bạn có thể tìm hiểu thêm về cách hoạt động của Chính sách về quyền trong bài viết Kiểm soát các tính năng của trình duyệt bằng Chính sách về quyền.