Kể từ Chrome 126, nhà phát triển có thể bắt đầu chạy bản dùng thử gốc cho một gói các tính năng API quản lý thông tin xác thực liên kết (FedCM) trên máy tính, cho phép một số trường hợp sử dụng Uỷ quyền. Gói này bao gồm API Tiếp tục và API Thông số, cho phép trải nghiệm giống như quy trình uỷ quyền OAuth liên quan đến hộp thoại cấp quyền do nhà cung cấp danh tính (IdP) cung cấp. Gói này cũng bao gồm các thay đổi khác như API Trường, Nhiều configURL và Nhãn tài khoản tuỳ chỉnh. Kể từ Chrome 126, chúng tôi cũng sẽ ra mắt một bản dùng thử gốc cho Storage Access API (SAA) tự động cấp các yêu cầu SAA nếu người dùng đã đăng nhập thành công bằng FedCM trước đây.
Bản dùng thử theo nguyên gốc: Gói FedCM Continuation API
Gói API Tiếp tục FedCM bao gồm nhiều đuôi FedCM:
API tiếp tục
Bạn có thể xem bản minh hoạ API trên Glitch.
API Tiếp tục cho phép điểm cuối xác nhận danh tính của IdP trả về một URL mà FedCM sẽ hiển thị để cho phép người dùng tiếp tục quy trình đăng nhập nhiều bước (không bắt buộc). Điều này cho phép IdP yêu cầu người dùng cấp quyền cho bên phụ thuộc (RP) ngoài những quyền có thể cấp trong giao diện người dùng FedCM hiện có, chẳng hạn như quyền truy cập vào tài nguyên phía máy chủ của người dùng.
Thông thường, điểm cuối xác nhận danh tính sẽ trả về một mã thông báo cần thiết để xác thực.
{
"token": "***********"
}
Tuy nhiên, với API Tiếp tục, điểm cuối xác nhận mã nhận dạng có thể trả về một thuộc tính continue_on
bao gồm đường dẫn tuyệt đối hoặc đường dẫn tương đối đến điểm cuối xác nhận mã nhận dạng.
{
// In the id_assertion_endpoint, instead of returning a typical
// "token" response, the IdP decides that it needs the user to
// continue on a pop-up window:
"continue_on": "/oauth/authorize?scope=..."
}
Ngay khi trình duyệt nhận được phản hồi continue_on
, một cửa sổ bật lên mới sẽ mở ra và chuyển người dùng đến đường dẫn đã chỉ định.
Sau khi người dùng tương tác với trang, chẳng hạn như cấp thêm quyền để chia sẻ thông tin bổ sung với RP, trang IdP có thể gọi IdentityProvider.resolve()
để phân giải lệnh gọi navigator.credentials.get()
ban đầu và trả về một mã thông báo dưới dạng đối số.
document.getElementById('allow_btn').addEventListener('click', async () => {
let accessToken = await fetch('/generate_access_token.cgi');
// Closes the window and resolves the promise (that is still hanging
// in the relying party's renderer) with the value that is passed.
IdentityProvider.resolve(accessToken);
});
Sau đó, trình duyệt sẽ tự đóng cửa sổ bật lên và trả mã thông báo về cho phương thức gọi API.
Nếu người dùng từ chối yêu cầu, bạn có thể đóng cửa sổ đó bằng cách gọi IdentityProvider.close()
.
IdentityProvider.close();
Nếu vì lý do nào đó mà người dùng đã thay đổi tài khoản của họ trong cửa sổ bật lên (ví dụ: IdP cung cấp chức năng "chuyển người dùng" hoặc trong trường hợp uỷ quyền), lệnh gọi phân giải sẽ lấy một đối số thứ hai không bắt buộc cho phép thực hiện một số thao tác như:
IdentityProvider.resolve(token, {accountId: '1234');
Parameters API (API Tham số)
Thông số API cho phép RP cung cấp thêm tham số cho điểm cuối của câu nhận định giá trị nhận dạng. Với Parameters API, bên bị hạn chế có thể truyền các tham số bổ sung đến IdP để yêu cầu quyền đối với các tài nguyên ngoài thông tin đăng nhập cơ bản. Người dùng sẽ uỷ quyền cho các quyền này thông qua quy trình trải nghiệm người dùng do IdP kiểm soát, được khởi chạy thông qua API Tiếp tục.
Để sử dụng API này, hãy thêm các tham số vào thuộc tính params
dưới dạng đối tượng trong lệnh gọi navigator.credentials.get()
.
let {token} = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
// Key/value pairs that need to be passed from the
// RP to the IdP but that don't really play any role with
// the browser.
params: {
IDP_SPECIFIC_PARAM: '1',
foo: 'BAR',
ETC: 'MOAR',
scope: 'calendar.readonly photos.write',
}
},
}
});
Tên thuộc tính trong đối tượng params
được thêm vào trước bằng param_
. Trong ví dụ trên, thuộc tính tham số chứa IDP_SPECIFIC_PARAM
là '1'
, foo
là 'BAR'
, ETC
là 'MOAR'
và scope
là 'calendar.readonly photos.write'
.
Lệnh này sẽ được dịch là
param_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
trong phần nội dung HTTP của yêu cầu:
POST /fedcm_assertion_endpoint HTTP/1.1
Host: 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=234234&disclosure_text_shown=false¶m_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
Tự động nhận quyền
Nhìn chung, đối với người dùng, việc yêu cầu cấp quyền khi cần thiết sẽ hữu ích nhất, thay vì khi nhà phát triển cảm thấy rằng đó là dễ triển khai nhất. Ví dụ: yêu cầu quyền truy cập vào camera khi người dùng sắp chụp ảnh sẽ được ưu tiên hơn là yêu cầu cấp quyền ngay khi người dùng truy cập vào trang web. Phương pháp tương tự cũng áp dụng cho tài nguyên máy chủ. Chỉ yêu cầu quyền khi người dùng cần. Phương thức này được gọi là "uỷ quyền động".
Để yêu cầu uỷ quyền một cách linh động bằng FedCM, IdP có thể:
- Gọi
navigator.credentials.get()
bằng các tham số bắt buộc mà IdP có thể hiểu được, chẳng hạn nhưscope
. - Điểm cuối xác nhận mã nhận dạng xác nhận người dùng đã đăng nhập và phản hồi bằng một URL
continue_on
. - Trình duyệt sẽ mở một cửa sổ bật lên có trang quyền của IdP để yêu cầu cấp thêm quyền phù hợp với phạm vi được yêu cầu.
- Sau khi được IdP uỷ quyền thông qua
IdentityProvider.resolve()
, cửa sổ sẽ đóng và lệnh gọinavigator.credentials.get()
ban đầu của RP sẽ nhận được mã thông báo hoặc mã uỷ quyền có liên quan để RP có thể trao đổi mã đó với mã truy cập thích hợp.
API Fields
API trường cho phép RP khai báo các thuộc tính tài khoản cần yêu cầu từ IdP để trình duyệt có thể hiển thị giao diện người dùng thông tin công bố thích hợp trong hộp thoại FedCM; IdP có trách nhiệm đưa các trường được yêu cầu vào mã thông báo được trả về. Hãy xem xét việc yêu cầu này một "hồ sơ cơ bản" trong OpenID Connect so với "phạm vi" trong OAuth.
Để sử dụng API Trường, hãy thêm các tham số vào thuộc tính fields
dưới dạng một mảng trong lệnh gọi navigator.credentials.get()
. Các trường hiện có thể chứa 'name'
, 'email'
và 'picture'
, nhưng có thể mở rộng để thêm nhiều giá trị hơn trong tương lai.
Yêu cầu với fields
sẽ có dạng như sau:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: ['name', 'email', 'picture'],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
Yêu cầu HTTP đến điểm cuối xác nhận mã nhận dạng bao gồm tham số fields
do RP chỉ định, với tham số disclosure_text_shown
được đặt là true
nếu đây không phải là người dùng cũ và các trường mà trình duyệt đã công bố cho người dùng trong tham số disclosure_shown_for
:
POST /id_assertion_endpoint HTTP/1.1
Host: 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=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture
Nếu RP cần quyền truy cập vào bất kỳ dữ liệu bổ sung nào từ IdP, chẳng hạn như quyền truy cập vào một lịch, thì bạn nên xử lý việc này bằng một thông số tuỳ chỉnh như đã đề cập ở trên. IdP trả về một URL continue_on
để yêu cầu quyền.
Nếu fields
là một mảng trống, thì yêu cầu sẽ có dạng như sau:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: [],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
Nếu fields
là một mảng trống, thì tác nhân người dùng sẽ bỏ qua giao diện người dùng công bố thông tin.
Điều này xảy ra ngay cả khi phản hồi từ điểm cuối tài khoản không chứa mã ứng dụng khớp với RP trong approved_clients
.
Trong trường hợp này, disclosure_text_shown
được gửi đến điểm cuối của câu nhận định mã nhận dạng sẽ là false trong phần nội dung HTTP:
POST /id_assertion_endpoint HTTP/1.1
Host: 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=234234&disclosure_text_shown=false
Nhiều configURLs
Nhiều configURL cho phép IdP lưu trữ nhiều tệp cấu hình cho một IdP, bằng cách chỉ định accounts_endpoint
và login_url
trong tệp well-known giống như các tệp cấu hình.
Nếu accounts_endpoint
và login_url
được thêm vào tệp well-known, thì provider_urls
sẽ bị bỏ qua để IdP có thể hỗ trợ nhiều tệp cấu hình.
Nếu không, provider_urls
sẽ tiếp tục có hiệu lực để tương thích ngược.
Tệp well-known hỗ trợ nhiều configURL có thể có dạng như sau:
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Điều này cho phép chúng tôi:
- Duy trì khả năng tương thích ngược và tiến với các tệp phổ biến hiện có và phiên bản cũ của trình duyệt đã được triển khai tự nhiên.
- Có số lượng tệp cấu hình tuỳ ý, miễn là tất cả các tệp đó đều trỏ đến cùng một
accounts_endpoint
vàlogin_url
. - Không có cơ hội để thêm entropy vào yêu cầu tìm nạp đã xác thực được gửi đến
accounts_endpoint
, vì bạn phải chỉ định entropy ở cấp "well-known".
Bạn không bắt buộc phải hỗ trợ nhiều configURL và các phương thức triển khai FedCM hiện có có thể giữ nguyên.
Nhãn tài khoản tùy chỉnh
Nhãn tài khoản tuỳ chỉnh cho phép các IDP FedCM chú thích tài khoản để các RP có thể lọc tài khoản bằng cách chỉ định nhãn trong tệp cấu hình. Bạn có thể lọc theo cách tương tự bằng cách sử dụng API gợi ý miền và API gợi ý đăng nhập bằng cách chỉ định các API đó trong lệnh gọi navigator.credentials.get()
, nhưng Nhãn tài khoản tuỳ chỉnh có thể lọc người dùng bằng cách chỉ định tệp cấu hình. Điều này đặc biệt hữu ích khi sử dụng nhiều configURL. Nhãn tài khoản tuỳ chỉnh cũng khác ở chỗ chúng được cung cấp từ máy chủ IdP, thay vì từ RP, chẳng hạn như gợi ý đăng nhập hoặc miền.
Ví dụ:
IdP hỗ trợ hai configURL tương ứng cho người tiêu dùng và doanh nghiệp. Tệp cấu hình người dùng có nhãn 'consumer'
và tệp cấu hình doanh nghiệp có nhãn 'enterprise'
.
Với cách thiết lập như vậy, tệp phổ biến sẽ bao gồm accounts_endpoint
và login_url
để cho phép nhiều configURL.
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Khi accounts_endpoint
được cung cấp trong tệp well-known, provider_urls
sẽ bị bỏ qua. RP có thể trỏ trực tiếp vào các tệp cấu hình tương ứng trong lệnh gọi navigator.credentials.get()
.
Tệp cấu hình của người dùng nằm tại https://idp.example/fedcm.json
, bao gồm cả thuộc tính accounts
chỉ định 'consumer'
bằng include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "consumer"
}
}
Tệp cấu hình doanh nghiệp nằm tại https://idp.example/enterprise/fedcm.json
,
bao gồm cả thuộc tính accounts
chỉ định 'enterprise'
bằng
include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/enterprise/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "enterprise"
}
}
Điểm cuối tài khoản phổ biến của IdP (trong ví dụ này là https://idp.example/accounts
) trả về danh sách các tài khoản có chứa thuộc tính nhãn được chỉ định labels
trong một mảng cho mỗi tài khoản.
Sau đây là ví dụ về phản hồi cho một người dùng có hai tài khoản. Một phiên bản dành cho người tiêu dùng và phiên bản còn lại dành cho doanh nghiệp:
{
"accounts": [{
"id": "123",
"given_name": "John",
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"labels": ["consumer"]
}], [{
"id": "4567",
"given_name": "Jane",
"name": "Jane Doe",
"email": "jane_doe@idp.example",
"picture": "https://idp.example/profile/4567",
"labels": ["enterprise"]
}]
}
Khi muốn cho phép người dùng 'enterprise'
đăng nhập, RP có thể chỉ định 'enterprise'
configURL 'https://idp.example/enterprise/fedcm.json'
trong lệnh gọi navigator.credentials.get()
:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
nonce: '234234',
configURL: 'https://idp.example/enterprise/fedcm.json',
},
}
});
Do đó, người dùng chỉ có thể đăng nhập bằng mã tài khoản '4567'
. Trình duyệt đã tự động ẩn mã tài khoản của '123'
để người dùng sẽ không được cung cấp một tài khoản không được IdP hỗ trợ trên trang web này.
Bản dùng thử theo nguyên gốc: FedCM làm tín hiệu tin cậy cho Storage Access API
Chrome 126 đang bắt đầu bản dùng thử theo nguyên gốc của FedCM làm tín hiệu tin cậy cho API Truy cập bộ nhớ. Với thay đổi này, việc cấp quyền trước đó thông qua FedCM sẽ trở thành lý do hợp lệ để tự động phê duyệt yêu cầu truy cập bộ nhớ của API Truy cập bộ nhớ.
Điều này rất hữu ích khi một iframe được nhúng muốn truy cập vào các tài nguyên được cá nhân hoá: chẳng hạn như nếu idp.example được nhúng trong rp.example và cần hiển thị tài nguyên được cá nhân hoá. Nếu trình duyệt hạn chế quyền truy cập vào cookie của bên thứ ba, ngay cả khi người dùng đăng nhập vào rp.example bằng idp.example bằng FedCM, thì iframe idp.example nhúng sẽ không thể yêu cầu tài nguyên được cá nhân hoá vì các yêu cầu sẽ không bao gồm cookie của bên thứ ba.
Để đạt được điều này, idp.example cần có quyền truy cập vào bộ nhớ thông qua iframe được nhúng trên trang web và điều này chỉ có thể nhận được thông qua lời nhắc cấp quyền.
Với FedCM làm tín hiệu tin cậy cho API Truy cập bộ nhớ, các bước kiểm tra quyền của API Truy cập bộ nhớ không chỉ chấp nhận việc cấp quyền do lời nhắc truy cập bộ nhớ cấp mà còn chấp nhận việc cấp quyền do lời nhắc FedCM cấp.
// In top-level rp.example:
// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://idp.example/fedcm.json',
clientId: '123',
}],
},
mediation: 'optional',
});
// In an embedded IdP iframe:
// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();
// This returns `true`.
const hasAccess = await document.hasStorageAccess();
Sau khi người dùng đăng nhập bằng FedCM, quyền này sẽ tự động được cấp miễn là quá trình xác thực FedCM đang hoạt động. Điều này có nghĩa là sau khi người dùng bị ngắt kết nối, việc yêu cầu quyền sẽ hiển thị lời nhắc.
Tham gia thử nghiệm về nguồn gốc
Bạn có thể dùng thử gói API Tiếp tục FedCM trên thiết bị bằng cách bật cờ Chrome
chrome://flags#fedcm-authz
trên Chrome 126 trở lên. Bạn cũng có thể dùng thử FedCM làm tín hiệu tin cậy cho API Truy cập bộ nhớ trên thiết bị bằng cách bật #fedcm-with-storage-access-api
trên Chrome 126 trở lên.
Những tính năng này cũng được cung cấp dưới dạng bản dùng thử theo nguyên gốc. Bản dùng thử theo nguyên gốc cho phép bạn dùng thử các tính năng mới và đưa ra ý kiến phản hồi về khả năng hữu dụng, tính thực tế và hiệu quả của các tính năng đó. Để biết thêm thông tin, hãy xem bài viết Bắt đầu thử nghiệm nguồn gốc.
Để dùng thử bản dùng thử nguồn gốc gói API Tiếp tục của FedCM, hãy tạo hai mã thông báo dùng thử nguồn gốc:
- Đăng ký dùng thử. Nhúng mã thông báo vào nguồn gốc của IdP.
- Đăng ký bản dùng thử theo nguyên gốc, sau đó chọn hộp đánh dấu so khớp bên thứ ba. Làm theo hướng dẫn trong phần Đăng ký bản dùng thử theo nguyên gốc của bên thứ ba cho RP để nhúng mã thông báo cho RP đó.
Nếu bạn muốn bật API Tiếp tục cùng với luồng nút, hãy bật cả bản dùng thử nguồn gốc API Chế độ nút:
- Đăng ký dùng thử phiên bản gốc với tư cách là bên thứ ba. Làm theo hướng dẫn trong phần Đăng ký bản dùng thử nguồn gốc của bên thứ ba cho RP để nhúng mã thông báo cho RP.
Cách dùng thử FedCM làm tín hiệu tin cậy cho bản dùng thử theo nguyên gốc Storage Access API:
- Đăng ký bản dùng thử theo nguyên gốc. Nhúng mã thông báo vào nguồn gốc của IdP.
Bản dùng thử theo nguyên gốc gói Continuation API và FedCM dưới dạng tín hiệu tin cậy cho bản dùng thử theo nguyên gốc Storage Access API có trong Chrome 126.
Đăng ký bản dùng thử nguồn gốc bên thứ ba cho RP
- Truy cập vào trang đăng ký bản dùng thử theo nguyên gốc.
- Nhấp vào nút Register (Đăng ký) rồi điền thông tin vào biểu mẫu để yêu cầu mã thông báo.
- Nhập nguồn gốc của IdP là Nguồn gốc web.
- Kiểm tra tính năng So khớp bên thứ ba để chèn mã thông báo bằng JavaScript trên các nguồn gốc khác.
- Nhấp vào Gửi.
- Nhúng mã thông báo đã phát hành trên trang web của bên thứ ba.
Để nhúng mã thông báo trên trang web của bên thứ ba, hãy thêm mã sau vào thư viện JavaScript hoặc SDK của IdP được phân phát từ nguồn gốc của IdP.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
Thay thế TOKEN_GOES_HERE
bằng mã thông báo của riêng bạn.