See the original blog version in English here.

Looking for a dev-focused passkey reference? Download our Passkeys Cheat Sheet. Trusted by dev teams at Ally, Stanford CS & more.
WebAuthn là tiêu chuẩn hiện đại đứng sau công nghệ passkey. Thay vì phụ thuộc vào mật khẩu truyền thống, nó tận dụng mật mã khóa công khai (public-key cryptography), cho phép người dùng xác thực bằng passkey - có thể bao gồm sinh trắc học (như vân tay hoặc nhận diện khuôn mặt) hoặc các khóa bảo mật vật lý (physical security keys). Sự chuyển đổi này không chỉ tăng cường bảo mật mà còn cải thiện trải nghiệm người dùng bằng cách loại bỏ hoàn toàn việc phải quản lý mật khẩu.
Tiêu chuẩn WebAuthn Level 3 giới thiệu các tính năng client
mới (client capabilities - có thể lấy được qua API trình duyệt getClientCapabilities()),
nhằm cung cấp cho lập trình viên và các nền tảng nhiều quyền kiểm soát và sự linh hoạt hơn
khi triển khai passkey. Những bản cập nhật này mang đến các cải tiến giúp đơn giản hóa quá
trình tích hợp passkey trên nhiều thiết bị, trình duyệt và nền tảng, đảm bảo một hành
trình người dùng mượt mà và đồng nhất hơn.
Trong bài đăng blog này, chúng ta sẽ cùng giải đáp các câu hỏi sau:
Đến cuối bài viết, bạn sẽ hiểu cách những tính năng này có thể giúp chúng ta tạo ra các luồng xác thực an toàn, liền mạch và đáp ứng được kỳ vọng của người dùng hiện đại.
Recent Articles
📖
Nhà cung cấp Passkey: loại, AAGUID & triển khai
🔑
Bằng Lái Xe Di Động đã ra mắt: Hướng dẫn toàn diện về mDL
📖
WebAuthn Related Origins: Hướng dẫn sử dụng Passkey trên nhiều tên miền
⚙️
WebAuthn Transports: Giải Thích Về Phương Thức Internal và Hybrid
🔑
Làm thế nào để chuyển đổi hoàn toàn sang không mật khẩu
Tính năng client của WebAuthn (WebAuthn client capabilities) là một tập hợp các chức năng cho phép trình duyệt và nền tảng thông báo những tính năng WebAuthn nào mà chúng hỗ trợ. Nói một cách đơn giản, chúng hoạt động như một "danh sách kiểm tra tính năng" giúp các trang web biết được phương thức xác thực và cài đặt nào khả dụng trên thiết bị của người dùng. Điều này cho phép chúng ta tùy chỉnh các luồng xác thực dựa trên khả năng của client, đảm bảo trải nghiệm người dùng trơn tru và bảo mật hơn.
Ví dụ, nếu trình duyệt báo hiệu rằng nó hỗ trợ xác thực sinh trắc học (như Touch ID), chúng ta có thể thiết kế luồng đăng nhập để cung cấp cho người dùng tùy chọn đăng nhập bằng dấu vân tay. Ngược lại, nếu trình duyệt không hỗ trợ một số tính năng nhất định, chúng ta có thể đưa ra các phương án dự phòng (fallback), như mật khẩu hoặc SMS OTP. Trong thực tế, các luồng tính năng không được hỗ trợ hoặc bị gián đoạn vẫn có thể hiển thị như các lỗi trình duyệt thông thường, do đó các nhóm phát triển nên ánh xạ những kết quả này vào một phân loại lỗi WebAuthn rõ ràng.
Tiêu chuẩn WebAuthn Level 3 giới thiệu một số tính năng
client mới giúp việc triển khai passkey trở nên linh hoạt và thân thiện với người dùng
hơn. Phiên bản đầu tiên hỗ trợ cho lệnh gọi API getClientCapabilities() đã được ra mắt
trong Safari 17.4.
Để kiểm tra hỗ trợ trong trình duyệt, đoạn mã (snippet) sau có thể sẽ hữu ích với bạn:
// Check if PublicKeyCredential is supported in the current browser if (typeof PublicKeyCredential === "undefined") { console.log("PublicKeyCredential is not supported in this browser."); } // Check if getClientCapabilities method exists on PublicKeyCredential if (typeof PublicKeyCredential.getClientCapabilities === "function") { try { let capabilities = await PublicKeyCredential.getClientCapabilities(); console.log(capabilities); } catch (error) { console.error("Error getting client capabilities:", error); } } else { console.log("getClientCapabilities is not supported in this browser"); }
getClientCapabilities() cho phép các trang web và ứng dụng truy vấn client (ví dụ: trình
duyệt hoặc thiết bị) để xác định xem nó hỗ trợ các tính năng WebAuthn nào. Bằng cách hiểu
rõ khả năng của client, chúng ta có thể tối ưu hóa các luồng xác thực để tận dụng các tính
năng sẵn có, như xác thực sinh trắc học, và cung cấp
các phương thức thay thế nếu thiếu một số tính năng.
Subscribe to our Passkeys Substack for the latest news.
Dưới đây là cái nhìn chi tiết hơn về các tính năng client của WebAuthn và tác động của chúng đến việc tích hợp passkey:
conditionalCreate kích hoạt tính năng
tạo passkey tự động dựa trên các điều
kiện cụ thể. Một ứng dụng có thể sử dụng tính năng này để tự động
tạo passkey trong quá trình
tự động điền mật khẩu nếu
trình quản lý mật khẩu có hỗ trợ tương ứng. Tính
năng này giúp thúc đẩy sự tiếp nhận passkey và sử
dụng về sau bằng cách tự động chuyển đổi người dùng từ mật khẩu sang passkey.
Tương tự như conditionalCreate, conditionalGet tự động kích hoạt quá trình đăng nhập
bằng passkey. Điều này rất hữu ích trong các kịch bản mà trải nghiệm passkey UX tốt nhất
cần được kích hoạt, làm cho quá trình đăng nhập không chỉ không cần mật khẩu
(passwordless) mà còn không cần tên người dùng (usernameless - người dùng chỉ cần nhấp vào
passkey đã chọn trong một modal / dropdown là có thể xác thực). Bằng cách sử dụng tính
năng này, chúng ta đảm bảo xác thực bằng passkey chỉ diễn ra khi phù hợp, giảm thiểu các
thông báo không cần thiết và nâng cao trải nghiệm người dùng.
hybridTransport đảm bảo passkey có thể được sử dụng trên nhiều thiết bị khác nhau, cho
phép xác thực chéo thiết bị liền mạch (qua
mã QR và Bluetooth). Ví dụ, một người
dùng có thể sử dụng passkey được lưu trên điện thoại thông minh của họ để đăng nhập vào
một dịch vụ trên máy tính để bàn. Tính năng này cho phép
xác thực an toàn mà không cần phải
chuyển passkey thủ công hoặc dựa vào các phương pháp đăng nhập
truyền thống cho từng thiết bị, tạo ra một trải nghiệm xác thực thống nhất.
Các authenticator của nền tảng (Platform authenticators), như Windows Hello, Face ID hoặc Touch ID, được tích hợp trực tiếp vào thiết bị và mang lại trải nghiệm passkey nhanh hơn, mượt mà hơn và bảo mật hơn bằng cách cho phép người dùng xác thực bằng sinh trắc học hoặc các phương pháp gốc khác của thiết bị (ví dụ: mã PIN).
Become part of our Passkeys Community for updates & support.
userVerifyingPlatformAuthenticator đảm bảo rằng
xác thực passkey có bao gồm
bước xác minh người dùng, chẳng hạn như quét vân tay
chủ động hoặc nhận diện khuôn mặt, cung cấp thêm một lớp bảo mật vững chắc.
Tính năng relatedOrigins cho phép xác thực liền mạch trên nhiều tên miền (domains) khác
nhau thuộc sở hữu của cùng một tổ chức (ví dụ: amazon.com và amazon.de). Ví dụ, nếu một
công ty quản lý nhiều tên miền hoặc có các tên miền phụ (subdomains) khác nhau, người dùng
có thể đăng nhập một lần và truy cập tất cả các tài sản số mà không cần phải xác thực lại
trên từng tên miền. Tính năng này hợp lý hóa trải nghiệm người dùng, giảm thiểu sự bất
tiện và đặc biệt giá trị đối với các doanh nghiệp hoạt động trong môi trường quốc tế hoặc
có các nền tảng đa dịch vụ.
Phương thức signalAllAcceptedCredentials(options) cung cấp danh sách đầy đủ các
Credential ID của WebAuthn cho một người dùng nhất định. Các Relying Party của WebAuthn
nên ưu tiên sử dụng phương thức này hơn là signalUnknownCredential() khi người dùng đã
xác thực xong, vì không có rủi ro rò rỉ quyền riêng tư. Phương thức này cung cấp cái nhìn
tổng quan toàn diện về public key credentials của người dùng, bao gồm mọi thay đổi gần đây
có thể chưa được cập nhật trên các authenticator đang được kết
nối hiện tại.
Hãy xem một ví dụ. Một người dùng (userId: A) có 2 passkey với các Credential ID được mã
hóa Base64URL là X và Y. Sau đó, người dùng xóa passkey X
trong cài đặt tài khoản của dịch vụ web (example.com) (do đó public key bị xóa). Bây
giờ, chúng ta chạy đoạn mã sau:
PublicKeyCredential.signalAllAcceptedCredentials({ rpId: "example.com", userId: "A", // WebAuthn User Handle, Base64URL. allAcceptedCredentialIds: ["Y"], });
Nếu authenticator có sẵn tại thời điểm đoạn mã trên thực thi, thì authenticator sẽ xóa hoặc ẩn passkey X khỏi các phiên xác thực trong tương lai. Tuy nhiên, authenticator có thể không được kết nối tại thời điểm thực thi, vì vậy các relying party được khuyến nghị nên chạy đoạn mã này định kỳ, ví dụ: ở mỗi lần đăng nhập.
Các passkey không có mặt trong allAcceptedCredentialIds sẽ bị xóa hoặc ẩn đi, có khả
năng không thể khôi phục được. Vì vậy, điều quan trọng là các relying party phải chú ý để
các WebAuthn Credential ID hợp lệ không bao giờ bị xóa khỏi danh sách. Nếu một
credential ID hợp lệ vô tình bị xóa, thì
relying party ngay lập tức phải đưa nó vào một lệnh gọi
signalAllAcceptedCredentials(options) khác càng sớm càng tốt để "bỏ ẩn" (unhide)
passkey. Nếu passkey không bị ẩn mà thực sự bị xóa, thì sẽ không có nhiều cách để khắc
phục.
Want to experiment with passkey flows? Try our Passkeys Debugger.
Phương thức signalCurrentUserDetails(options) phát tín hiệu về tên hiện tại của người
dùng và WebAuthn Display Name. Khi signalCurrentUserDetails(options) được gọi, client sẽ
tuân theo một bộ các bước đã định nghĩa để thực thi hành động này.
Hãy xem một ví dụ. Một người dùng có WebAuthn User ID
là A cập nhật tên của họ trong phần cài đặt tài khoản của trang web (example.com). Sau
đó, relying party có thể chạy đoạn mã sau:
PublicKeyCredential.signalCurrentUserDetails({ rpId: "example.com", userId: "A", // user ID, Base64URL. name: "New user name", displayName: "New display name", });
Authenticator sau đó sẽ cập nhật siêu dữ liệu (metadata) của passkey được lưu cục bộ. Lợi ích lớn nhất là trong các yêu cầu Conditional UI / tự động điền passkey tương lai, menu lựa chọn / dropdown của Conditional UI sẽ hiển thị tên và WebAuthn Display Name đã được cập nhật.
Phương thức signalUnknownCredential(options) thông báo rằng một
Credential ID của WebAuthn không được nhận diện bởi
WebAuthn Relying Party, ví dụ như trong trường hợp passkey đã
bị người dùng xóa. Khác với signalAllAcceptedCredentials(options), phương thức này không
yêu cầu cung cấp danh sách đầy đủ các Credential ID đã được chấp nhận và WebAuthn
User Handle, qua đó ngăn chặn nguy cơ rò rỉ quyền
riêng tư đối với những người gọi API chưa xác thực.
Hãy xem một ví dụ. Một người dùng xóa một passkey có
credential ID X trên cài đặt tài khoản của một
trang web (example.com) (đồng nghĩa với việc public key bị xóa). Tuy nhiên, private key
vẫn có sẵn trên thiết bị của người dùng. Điều này có nghĩa là trong các yêu cầu đăng nhập
Conditional UI /
tự động điền passkey tương lai (với
danh sách allowCredentials trống), passkey đó vẫn có thể được chọn. Tuy nhiên, nỗ lực
đăng nhập sẽ thất bại do public key đã bị xóa, vậy nên relying party cần phải chạy lệnh:
PublicKeyCredential.signalUnknownCredential({ rpId: "example.com", credentialId: "X", // credential ID the user just tried, Base64URL });
Khi đó authenticator sẽ xóa hoặc ẩn passkey với Credential ID X khỏi các bước xác thực
sau này.
Do tiêu chuẩn WebAuthn Level 3 vẫn đang ở trạng thái nháp (draft), việc áp dụng các tính năng client mới này vẫn chưa hoàn toàn phổ biến. Các trình duyệt khác nhau đang dần dần triển khai các tính năng này, nhưng sự hỗ trợ có thể khác nhau. Dưới đây là tổng quan được cập nhật về tính khả dụng trên các trình duyệt lớn đã đề cập ở trên:
| Trình duyệt | Phiên bản hỗ trợ Client Capabilities | Ghi chú |
|---|---|---|
| Chrome | 133 | Chrome Platform Status & Chromium Bug Tracker |
| Safari | 17.4+ | Trình duyệt đầu tiên ra mắt getClientCapabilities(). Tính đến tháng 10 năm 2024, Safari hỗ trợ các tính năng như conditionalCreate, conditionalMediation, hybridTransport, passkeyPlatformAuthenticator, và userVerifyingPlatformAuthenticator. |
| Edge | 133 | Dựa trên Chromium 133. Chromium Bug Tracker |
| Firefox | 135 | Mozilla đã bắt đầu triển khai các tính năng client WebAuthn Level 3 trên Firefox 135 trở lên. |
Tốc độ áp dụng có thể sẽ tăng tốc khi Level 3 hoàn thiện và có nhiều trình duyệt phát hành
các tính năng này hơn. Nếu bạn muốn biết hiện có bao nhiêu người dùng có thể tận dụng
getClientCapabilities(), bạn có thể kiểm tra dữ liệu thực tế bằng công cụ miễn phí
State of Passkeys. Hãy theo dõi các ghi chú phát hành của
trình duyệt và tài liệu liên quan để lên kế hoạch cho khả năng tương thích rộng hơn khi nó
phát triển.
Want to find out how many people use passkeys?
Là một lập trình viên, bạn có thể tự hỏi việc phát hiện các tính năng client mới này của WebAuthn có ý nghĩa gì đối với mình và cách sử dụng chúng trong ứng dụng. Dưới đây là một số khuyến nghị để áp dụng chúng.
Tuy nhiên, hãy lưu ý rằng chưa phải tất cả các trình duyệt đều hỗ trợ lệnh gọi API
getClientCapabilities() (tính đến tháng 11 năm 2024). Có một bộ polyfill có sẵn
tại đây, có thể được sử dụng cho đến
khi tất cả các trình duyệt bắt kịp xu hướng.
Hãy sử dụng getClientCapabilities() sớm trong mã nguồn của bạn để phát hiện các tính
năng được client hỗ trợ ngay từ lúc bắt đầu tải trang / luồng xác thực. Điều này sẽ cho
phép bạn tùy chỉnh trải nghiệm một cách linh hoạt, và cung cấp các
tính năng passkey phù hợp với
thiết bị / trình duyệt, ví dụ như thúc đẩy xác thực nền tảng (platform authentication) khi
được hỗ trợ hoặc đưa ra các phương thức thay thế (ví dụ:
SMS OTP hoặc
khóa bảo mật phần cứng) nếu không
có.
Nếu bạn thêm passkey vào một trang web / ứng dụng hiện đang dùng mật khẩu, tính năng
conditionalCreate có thể là một cú hích thực sự cho
việc tiếp nhận passkey của bạn. Trong nền, khi
thực hiện tự động điền mật khẩu bằng một trình quản lý
thông tin xác thực phù hợp (chỉ có Apple Passwords
tính đến tháng 10 năm 2024), một passkey sẽ tự động được tạo ra và sẽ được ưu tiên trong
những lần điền tự động sau này.
Để không chỉ có tỷ lệ tiếp nhận passkey cao, mà
còn tỷ lệ đăng nhập bằng passkey cao, hãy cố gắng
kiểm tra xem thiết bị / trình duyệt có thể sử dụng Conditional UI /
Passkey Autofill hay không bằng cách
kiểm tra conditionalGet. Cách này sẽ khuyến khích người dùng sử dụng passkey đã tạo cho
các lần đăng nhập, vì nó được hệ điều hành / trình duyệt chủ động đề xuất và thậm chí còn
yêu cầu ít nỗ lực hơn việc tự động điền mật khẩu.
Hãy tận dụng hybridTransport để kích hoạt xác thực chéo thiết bị (qua
mã QR và Bluetooth), cho phép người dùng
đăng nhập mượt mà từ điện thoại thông minh của họ, ngay cả khi họ đang truy cập dịch vụ
của bạn trên máy tính để bàn.
Các tính năng client của WebAuthn đại diện cho một bước tiến đáng kể trong việc giải quyết những khoảng trống hiện có của passkey. Trong bài đăng blog này, chúng ta đã giải quyết những câu hỏi chính về các tính năng client của WebAuthn:
getClientCapabilities, conditionalCreate, hybridTransport, v.v.Chúng tôi khuyến khích bạn khám phá các tính năng mới của WebAuthn Level 3 và luôn cập nhật tình hình hỗ trợ trên các trình duyệt. Nếu bạn đang tìm cách triển khai passkey và tận dụng những khả năng nâng cao này, hãy liên hệ với chúng tôi để được tư vấn và hỗ trợ chuyên sâu.
Hãy gọi getClientCapabilities() sớm trong quá trình tải trang hoặc luồng xác thực để chủ động phát hiện các tính năng được hỗ trợ. Điều này giúp chúng ta cung cấp xác thực nền tảng (platform authentication) khi được hỗ trợ, hoặc chuyển sang các phương án dự phòng như SMS OTP hoặc khóa bảo mật phần cứng (hardware security keys) khi không có hỗ trợ.
signalAllAcceptedCredentials yêu cầu danh sách đầy đủ các Credential ID hợp lệ và WebAuthn User Handle, do đó chỉ nên gọi khi người dùng đã xác thực để tránh rò rỉ quyền riêng tư. signalUnknownCredential thông báo một Credential ID không được nhận diện duy nhất mà không yêu cầu toàn bộ danh sách, giúp việc gọi API này an toàn trong các kịch bản chưa xác thực, chẳng hạn như sau một lần đăng nhập thất bại.
Tính năng relatedOrigins cho phép xác thực liền mạch trên nhiều tên miền khác nhau thuộc sở hữu của cùng một tổ chức, ví dụ amazon.com và amazon.de. Người dùng có thể đăng nhập một lần và truy cập tất cả tài sản mà không cần xác thực lại trên mỗi tên miền, điều này làm giảm độ ma sát trong môi trường quốc tế hoặc đa dịch vụ.
Tính đến tháng 11 năm 2024, chưa phải tất cả trình duyệt đều hỗ trợ getClientCapabilities(), vì vậy bạn có thể sử dụng polyfill tại github.com/MasterKale/webauthn-polyfills như một giải pháp thay thế tạm thời. Việc áp dụng dự kiến sẽ tăng tốc khi tiêu chuẩn WebAuthn Level 3 trưởng thành, và hiện Chrome 133, Edge 133, Firefox 135 cũng như Safari 17.4 đã chính thức hỗ trợ.
Related Articles
Table of Contents