Trang này được dịch tự động. Đọc phiên bản gốc bằng tiếng Anh tại đây.

Cheatsheet Passkeys. Hướng dẫn thực tế, mẫu triển khai và KPI cho chương trình passkeys.
isConditionalMediationAvailable() trước khi bắt đầu bất kỳ luồng Conditional
UI nào để ngăn chặn các lỗi hiển thị cho người dùng trên các trình duyệt hoặc thiết bị không được hỗ trợ.autocomplete="username webauthn" trên trường đầu vào HTML báo hiệu cho
trình duyệt hiển thị passkey cùng với các đề xuất mật khẩu trong menu thả xuống tự động điền.mediation: "conditional" trong lệnh gọi navigator.credentials.get()
sẽ kích hoạt tính năng tự động điền passkey mà không làm gián đoạn người dùng bằng một hộp thoại phương thức (modal dialog) chặn ngang màn hình.AbortController để hủy các yêu cầu Conditional UI đang diễn ra vì
menu thả xuống tự động điền, không giống như các lời nhắc phương thức, không có nút hủy tích hợp sẵn.Với sự áp dụng nhanh chóng của passkey (và giao thức WebAuthn cơ bản), việc xác thực đã trở nên an toàn và thân thiện hơn đối với nhiều người dùng. Một trong những tiến bộ nổi bật của passkey là sự tích hợp của Conditional UI, thường được gọi là "tự động điền passkey" (passkey autofill) hoặc Conditional Mediation (trong phần tiếp theo, chúng ta sẽ thống nhất sử dụng thuật ngữ Conditional UI).
Bất chấp việc mới được giới thiệu và đang tiếp tục được các trình duyệt áp dụng, vẫn có một khoảng trống dễ nhận thấy trong tài liệu kỹ thuật và lời khuyên triển khai đối với Conditional UI. Bài viết này nhằm mục đích thu hẹp khoảng cách đó bằng cách giải thích Conditional UI là gì, cách hoạt động và cách giải quyết các thách thức phổ biến trong quá trình triển khai.
Bài viết gần đây
⚙️
Tài liệu Cheat Sheet về Passkey cho Lập trình viên
👤
Cách Xóa Passkey trên Apple, Windows và Android
📖
Giải thích Kỹ thuật về WebAuthn Conditional UI (Tự động điền Passkey)
📖
Hướng dẫn toàn diện về lỗi WebAuthn trong môi trường Production (2026)
📖
Passkey trên Brave Browser (2026): Điều gì hoạt động và điều gì bị lỗi
Conditional UI đại diện cho một chế độ mới đối với quy trình đăng nhập passkey / WebAuthn. Nó hiển thị passkey một cách có chọn lọc trên giao diện người dùng (UI) chỉ khi người dùng có thông tin xác thực có thể khám phá (khóa thường trú) - một loại passkey, được đăng ký với bên phụ thuộc (dịch vụ trực tuyến) và được lưu trữ trong trình xác thực trên thiết bị của họ (ví dụ: máy tính xách tay, điện thoại thông minh). Các passkey được hiển thị trong menu thả xuống kết hợp với các mật khẩu được tự động điền, mang lại sự chuyển đổi liền mạch giữa hệ thống mật khẩu truyền thống và xác thực passkey tiên tiến, vì người dùng nhìn thấy cả hai trong cùng một ngữ cảnh. Cách tiếp cận thông minh này đảm bảo rằng người dùng không bị choáng ngợp bởi các tùy chọn không cần thiết và có thể điều hướng quá trình đăng nhập liền mạch hơn.
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
We hit 80% mobile passkey activation across 5M+ users without replacing our IDP.
See how VicRoads scaled passkeys to 5M+ users — alongside their existing IDP.
Read the case studyNền tảng của Conditional UI được xây dựng dựa trên ba trụ cột chính:
Đăng ký Passkeys Substack để nhận tin mới nhất.
Trong phần tiếp theo, chúng tôi cung cấp thông tin chi tiết từng bước về các bước đơn lẻ của toàn bộ luồng Conditional UI:
Nhìn chung, quy trình luồng Conditional UI có thể được chia thành hai giai đoạn. Trong giai đoạn tải trang, logic Conditional UI diễn ra dưới nền, trong khi ở giai đoạn thao tác của người dùng, người dùng phải chủ động thực hiện một hành động nào đó.
isConditionalMediationAvailable() để phát hiện xem kết hợp trình duyệt / thiết bị
hiện tại có hỗ trợ Conditional UI hay không. Chỉ khi phản hồi là true, quá trình mới
tiếp tục, nếu không quá trình Conditional UI sẽ bị hủy.credentials.get() với
PublicKeyCredentialRequestOptions đã nhận và
thuộc tính mediation được đặt thành conditional, quá trình xác thực
cục bộ trên thiết bị sẽ bắt đầu.Bằng cách tuân theo quy trình này, Conditional UI mang đến trải nghiệm xác thực liền mạch và thân thiện với người dùng.
Để Conditional UI hoạt động, một số khía cạnh chung cần được xem xét:
Tham gia Passkeys Community để nhận cập nhật và hỗ trợ.
Để đưa Conditional UI vào hoạt động ở phía máy khách, các yêu cầu sau phải được đáp ứng:
isConditionalMediationAvailable() và kiểm tra tính khả dụng kỹ thuật
của Conditional UI ( xem bên dưới để biết
thêm chi tiết).Để Conditional UI hoạt động, một số yêu cầu ở phía máy chủ cũng phải được đáp ứng:
Kể từ khi chính thức ra mắt Conditional UI vào cuối năm 2022 và các phiên bản beta trước đó, chúng tôi đã thử nghiệm và làm việc sâu rộng với tính năng này. Trong phần tiếp theo, chúng tôi muốn chia sẻ với bạn các mẹo thực tế đã giúp ích trong quá trình triển khai Conditional UI.
Thử nghiệm các luồng passkey trong Passkeys Debugger.
Một ví dụ mã đơn giản và đầy đủ cho phương thức Conditional UI sẽ trông như thế này:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Conditional UI</title> </head> <body> <input type="text" id="username" autocomplete="username webauthn" /> <script> async function passkeyLogin() { try { // retrieve the request options (incl. the challenge) from the WebAuthn server let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); const userData = await WebAuthnClient.sendSignedChallenge(credential); window.location.href = "/logged-in"; } catch (error) { console.log(error); } } passkeyLogin(); </script> </body> </html>
Triển khai việc phát hiện Conditional UI đảm bảo rằng Conditional UI chỉ được sử dụng khi
kết hợp thiết bị / trình duyệt hiện tại hỗ trợ tính năng này. Điều này sẽ hoạt động mà không xuất hiện
các lỗi hiển thị cho người dùng khi thiếu hỗ trợ Conditional UI. Việc kết hợp phương thức
isConditionalMediationAvailable() trong giao diện người dùng sẽ giải quyết
mối quan tâm này. Nếu có hỗ trợ Conditional UI, quy trình đăng nhập Conditional UI có thể được bắt đầu.
// source: https://developer.mozilla.org/en-US/docs/Web/API/PublicKeyCredential/isConditionalMediationAvailable#examples // Availability of `window.PublicKeyCredential` means WebAuthn is usable. if (window.PublicKeyCredential && PublicKeyCredential.isConditionalMediationAvailable) { // Check if conditional mediation is available. const isCMA = await PublicKeyCredential.isConditionalMediationAvailable(); if (isCMA) { // Call WebAuthn authentication start endpoint let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); /* ... */ } }
Trường đầu vào nên nhận một token tự động điền HTML webauthn. Điều này báo hiệu cho máy khách điền passkey vào yêu cầu đang diễn ra. Bên cạnh passkey, các giá trị tự động điền khác cũng có thể được hiển thị. Các token tự động điền này có thể được kết hợp với các token hiện có khác, ví dụ:
autocomplete="username webauthn": Bên cạnh việc hiển thị passkey, nó cũng đề xuất
tự động điền tên người dùng.autocomplete="current-password webauthn": Bên cạnh việc hiển thị passkey, nó tiếp tục
nhắc tự động điền mật khẩu.<label for="name">Username:</label> <input type="text" name="name" autocomplete="username webauthn" /> <label for="password">Password:</label> <input type="password" name="password" autocomplete="current-password webauthn" />
Để biết thêm chi tiết, chúng tôi khuyên bạn nên đọc bài đăng trên blog này, cung cấp thêm thông tin chi tiết về các token autofill / autocomplete cho passkey và mật khẩu.
Để lấy các passkey có sẵn sau khi đã nhận đối tượng PublicKeyCredentialRequestOptions,
hàm navigator.credentials.get() nên được gọi (phục vụ cho cả
passkey và mật khẩu). Đối tượng PublicKeyCredentialRequestOptions cần có
tham số mediation được đặt thành conditional để kích hoạt Conditional UI trên máy khách. Đối với các trường hợp
bạn muốn có lời nhắc passkey theo phương thức (modal) thay thế, hãy xem
mediation ngay lập tức (immediate mediation).
const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", });
Nếu không có passkey khả dụng, hoặc người dùng bỏ qua các passkey được đề xuất và nhập email của họ, luồng Conditional UI sẽ bị dừng. Điều này nhấn mạnh tầm quan trọng của việc luôn hỗ trợ quá trình đăng nhập passkey / WebAuthn tiêu chuẩn thông qua một hộp thoại phương thức (modal).
Một điểm quan trọng cần nhấn mạnh ở đây là nhu cầu tiềm tàng đối với việc tạm dừng yêu cầu Conditional UI đang diễn ra. Trái ngược với trải nghiệm phương thức, các menu thả xuống tự động điền không có nút hủy. Theo thiết kế của WebAuthn, chỉ nên có một yêu cầu thông tin xác thực hoạt động duy nhất đang diễn ra tại bất kỳ thời điểm nào. Tiêu chuẩn WebAuthn gợi ý sử dụng AbortController để hủy một quy trình WebAuthn, áp dụng cho cả quy trình đăng nhập thông thường và Conditional UI (xem tại đây để biết chi tiết).
Trong dữ liệu đo lường sản xuất (production telemetry), đường dẫn hủy này thường là một kết quả kiểm soát luồng (control-flow) dự kiến, không phải là lỗi hệ thống. Nếu bạn thấy khối lượng lỗi lớn, bạn cần phân loại các trường hợp dự kiến so với các trường hợp không mong muốn theo loại hoạt động và thời gian trước khi coi chúng là sự sụt giảm hiệu suất (regression).
Quy trình đăng nhập Conditional UI được kích hoạt ngay khi người dùng truy cập trang.
Nhiệm vụ đầu tiên nên là tạo một đối tượng AbortController có phạm vi toàn cục. Đối tượng này sẽ đóng vai trò
là tín hiệu để máy khách của bạn chấm dứt yêu cầu tự động điền, đặc biệt là nếu người dùng
quyết định thực hiện quy trình đăng nhập passkey thông thường.
Đảm bảo rằng AbortController có thể được gọi bởi các hàm khác và được thiết lập lại (reset) nếu
quy trình Conditional UI phải khởi động lại. Sử dụng thuộc tính signal trong
lệnh gọi navigator.credentials.get(), kết hợp tín hiệu AbortController của bạn làm
giá trị của nó. Điều này báo hiệu cho hàm passkey / WebAuthn rằng yêu cầu phải bị dừng nếu
tín hiệu bị hủy. Hãy nhớ thiết lập một AbortController mới mỗi khi bạn
kích hoạt Conditional UI. Việc sử dụng AbortController đã bị hủy (aborted) sẽ dẫn đến việc hủy ngay lập tức
hàm passkey / WebAuthn. Các bước còn lại phù hợp với quy trình đăng nhập
passkey thông thường. Trong phần sau, bạn sẽ thấy một
ví dụ mã của các bước được đề cập:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Conditional UI</title> </head> <body> <input type="text" id="username" autocomplete="username webauthn" /> <script> async function passkeyLogin() { try { // retrieve the request options (incl. the challenge) from the WebAuthn server let options = await WebAuthnClient.getPublicKeyRequestOptions(); const credential = await navigator.credentials.get({ publicKey: options.publicKeyCredentialRequestOptions, mediation: "conditional", }); const userData = await WebAuthnClient.sendSignedChallenge(credential); window.location.href = "/logged-in"; } catch (error) { console.log(error); } } passkeyLogin(); </script> </body> </html>
Trong trường hợp không hỗ trợ Conditional UI, hãy điều hướng người dùng hướng tới quy trình đăng nhập passkey thông thường. Cung cấp đường dẫn này là quan trọng đối với những người dùng dựa vào khóa bảo mật phần cứng (ví dụ: YubiKeys) hoặc những người buộc phải sử dụng khóa không thường trú / thông tin xác thực không thể khám phá do các giới hạn của trình xác thực.
Xem có bao nhiêu người thực sự dùng passkeys.
Khi bạn phát triển một ứng dụng gốc, ví dụ: cho iOS hoặc Android, Conditional UI cũng sẽ hoạt động. Sẽ không có vấn đề gì nếu bạn triển khai nó một cách tự nhiên (natively) bằng Flutter, Kotlin hay Swift, hoặc nếu bạn quyết định sử dụng Chrome Custom Tabs (CCT) hay SFSafariViewController hay SFAuthenticationSession / ASWebAuthenticationSession. Cả hai phương pháp tiếp cận đều hỗ trợ Conditional UI.
Nhìn chung, chúng tôi hầu như không tìm thấy tài liệu nào về cách triển khai hỗ trợ Conditional UI cho ứng dụng iOS. Tuy nhiên, trong quá trình nghiên cứu, chúng tôi đã phát hiện ra hai cách để thêm hỗ trợ Conditional UI cho ứng dụng iOS, vì trải nghiệm người dùng cũng sẽ khác nhau.
Loại A: Lớp phủ (Overlay) / Cửa sổ bật lên (Popup) trên Hầu hết Toàn bộ Màn hình
Loại A đầu tiên hiển thị một lớp phủ / cửa sổ bật lên kéo dài hầu hết trên toàn bộ màn hình. Tại đây, bạn sẽ thấy tất cả các passkey có sẵn đối với bên phụ thuộc này. Một ví dụ nổi bật triển khai Conditional UI theo cách này là KAYAK. Lớp phủ / cửa sổ bật lên tự động hiện ra khi người dùng mở đúng màn hình.
Loại B: Tự động điền trên Bàn phím (Keyboard Autofill)
Loại B thứ hai hiển thị một passkey phù hợp trong phần tự động điền của bàn phím
(nơi các mật khẩu cũng được đề xuất để tự động điền). Nhấp vào giá trị được đề xuất sẽ
thực hiện xác thực Face ID và cho phép bạn đăng nhập. Trong
phiên bản ứng dụng iOS hiện tại của bảng điều khiển dành cho nhà phát triển Corbado, chúng tôi đã triển khai theo cách này
(xem thông báo Sign in with passkey for <relying party ID> cùng với tên người dùng WebAuthn). Để hiển thị, người dùng cần chạm vào trường đầu vào:
Tính năng tự động điền passkey trong phần bàn phím này có thể gặp sự cố khi iOS mới được cài đặt vì dường như có một dạng bộ nhớ đệm (caching) diễn ra ở nền để tra cứu tất cả các passkey khả dụng cho bên phụ thuộc này.
Nhấp vào biểu tượng chìa khóa ở bên phải của passkey được đề xuất sẽ dẫn đến giao diện quen thuộc để chọn mật khẩu / passkey trong iOS:
Xin lưu ý rằng chúng tôi chưa tìm thấy tài liệu chính thức, và những hiểu biết của chúng tôi dựa trên kinh nghiệm và giả thuyết của chúng tôi thay vì bằng chứng cụ thể về cách triển khai thích hợp.
Trong Android, câu chuyện về Conditional rõ ràng hơn một chút, vì chỉ có một dạng cho Conditional UI / tự động điền passkey tận dụng API Credential Manager của Android (xem tài liệu tại đây). Bởi vì các nhà cung cấp Android có thể khác nhau, hãy theo dõi các lỗi passkey của Credential Manager tách biệt với các mẫu lỗi WebAuthn chỉ dành cho trình duyệt.
Mở trang nơi Conditional UI được triển khai sẽ hiển thị màn hình sau, nơi bạn sẽ tìm thấy các cách khác nhau để đăng nhập:
Nhấp vào More saved sign-ins cung cấp thêm nhiều tùy chọn để chọn cho việc đăng nhập (bao gồm xác thực chéo thiết bị và lựa chọn một nền tảng đồng bộ passkey khác, ví dụ: Samsung Pass hoặc 1Password):
Để minh họa Conditional UI trông như thế nào đối với người dùng cuối, chúng tôi đã thêm một số ảnh chụp màn hình về menu tự động điền Conditional UI bằng cách sử dụng https://passkeys.eu.
Thử passkeys trong demo trực tiếp.
Hãy cùng xem xét một số kịch bản phổ biến trong các ứng dụng thực tế.
Nếu không có passkey nào được lưu cho một trang web, Conditional UI sẽ hoạt động khác nhau tùy thuộc vào trình duyệt và hệ điều hành.
Trên Chrome dành cho macOS, nhấp vào trường đầu vào sẽ hiển thị một menu thả xuống tự động điền trống:
Trên Safari dành cho macOS, không có menu thả xuống nào được hiển thị - chỉ có một biểu tượng nhỏ mờ nhạt trong trường đầu vào:
Trên Android hoặc iOS, giao diện tự động điền chỉ xuất hiện nếu người dùng chạm vào trường đầu vào và hệ điều hành tìm thấy các thông tin xác thực phù hợp.
Sự biến đổi này là có chủ ý và là một phần của mô hình quyền riêng tư của WebAuthn: các trang web không thể phát hiện xem người dùng có passkey hay không trừ khi người dùng chủ động chọn một.
Nếu một người dùng cài đặt nhiều nhà cung cấp passkey (ví dụ: iCloud Keychain, Google Password Manager, 1Password), trình duyệt hoặc hệ điều hành sẽ thường mặc định chọn trình quản lý thông tin xác thực chính của người dùng.
Để biết danh sách các nhà cung cấp passkey / trình quản lý thông tin xác thực khác nhau hỗ trợ passkey, chúng tôi khuyên bạn nên xem qua liên kết GitHub sau đây.
Trên Android, Credential Manager cho thấy các nhà cung cấp khác nhau như Samsung Pass hoặc 1Password.
Trên iOS, biểu tượng chìa khóa sẽ mở danh sách đầy đủ các passkey từ nhiều nguồn khác nhau.
Là một ứng dụng hoặc trang web, bạn không thể kiểm soát trình quản lý thông tin xác thực nào được sử dụng - hệ điều hành quản lý lựa chọn đó để bảo vệ quyền riêng tư của người dùng.
Passkey, với khả năng Conditional UI / tự động điền passkey, là phương pháp xác thực trực tuyến mới. Khi chúng ta chuyển sang một kỷ nguyên nơi mật khẩu ngày càng được thay thế nhiều hơn bởi passkey, nhu cầu về các cơ chế chuyển đổi mạnh mẽ và thân thiện với người dùng là không thể phủ nhận. Bài viết này đã giúp hiểu cách triển khai Conditional UI một cách chính xác, một sự trợ giúp tuyệt vời trong quá trình chuyển đổi và những khía cạnh nào cần đặc biệt lưu ý.
Corbado là Authentication Intelligence Platform dành cho các đội CIAM vận hành xác thực consumer ở quy mô lớn. Chúng tôi giúp bạn nhìn thấy điều mà log IDP và các công cụ analytics thông thường không thấy: những thiết bị, phiên bản OS, trình duyệt và trình quản lý credential nào hỗ trợ passkey, tại sao quá trình đăng ký không chuyển thành đăng nhập, luồng WebAuthn fail ở đâu, và khi nào một bản cập nhật OS hay trình duyệt làm hỏng đăng nhập một cách âm thầm — tất cả mà không cần thay thế Okta, Auth0, Ping, Cognito hay IDP nội bộ của bạn. Hai sản phẩm: Corbado Observe bổ sung observability cho passkey và mọi phương thức đăng nhập khác. Corbado Connect mang đến managed passkey với analytics tích hợp (song hành cùng IDP của bạn). VicRoads vận hành passkey cho hơn 5M người dùng với Corbado (kích hoạt passkey +80%). Trao đổi với chuyên gia Passkey →
Gọi PublicKeyCredential.isConditionalMediationAvailable() và chỉ tiếp tục nếu
nó trả về true. Kiểm tra này ngăn chặn các lỗi hiển thị cho người dùng trên các sự kết hợp trình duyệt và thiết bị
không được hỗ trợ. Phương thức này nên được đánh giá trên mỗi lần tải trang trước khi gọi
navigator.credentials.get() với mediation: "conditional".
Trình xác thực chỉ lưu trữ dữ liệu dành riêng cho người dùng chẳng hạn như tên và tên hiển thị đối với khóa thường trú (thông tin xác thực có thể khám phá). Các khóa không thường trú không giữ lại thông tin này, vì vậy menu tự động điền không thể điền các thông tin chi tiết về tài khoản để người dùng lựa chọn.
Hành vi thay đổi tùy theo nền tảng. Chrome trên macOS hiển thị một menu thả xuống tự động điền trống, Safari trên macOS chỉ hiển thị một biểu tượng mờ nhạt trong trường đầu vào và trên Android hoặc iOS, giao diện tự động điền chỉ xuất hiện nếu hệ điều hành tìm thấy thông tin xác thực phù hợp sau khi người dùng chạm vào trường đó. Sự khác biệt này là cố ý và nằm trong một phần của mô hình quyền riêng tư của WebAuthn: các trang web không thể phát hiện xem passkey có tồn tại hay không trừ khi người dùng chủ động chọn một.
Tạo một AbortController ở phạm vi toàn cục và truyền tín hiệu (signal) của nó cho
navigator.credentials.get(). Gọi .abort() trên bộ điều khiển (controller) khi người dùng khởi tạo
luồng đăng nhập bằng phương thức (modal). Luôn khởi tạo (instantiate) một AbortController mới mỗi khi Conditional UI
khởi động lại, bởi vì việc sử dụng lại một bộ điều khiển đã bị hủy sẽ dẫn đến việc hủy ngay lập tức
yêu cầu WebAuthn.
Conditional UI hoạt động trong cả ứng dụng iOS và Android gốc. iOS hỗ trợ hai biến thể: một cửa sổ bật lên (popup) lớp phủ toàn màn hình và một gợi ý tự động điền trên bàn phím. Android sử dụng API Credential Manager, có thể hiển thị passkey từ nhiều nhà cung cấp khác nhau như Samsung Pass hoặc 1Password.
Bài viết liên quan
Mục lục