Get your free and exclusive 80-page Banking Passkey Report
Back to Overview

Cách xây dựng Trình xác minh thông tin xác thực kỹ thuật số (Hướng dẫn cho nhà phát triển)

Tìm hiểu cách xây dựng một trình xác minh thông tin xác thực kỹ thuật số từ đầu bằng Next.js, OpenID4VP và ISO mDoc. Hướng dẫn chi tiết này sẽ chỉ cho bạn cách tạo một trình xác minh có thể yêu cầu, nhận và xác thực giấy phép lái xe di động cùng các thông

Amine

Created: August 20, 2025

Updated: August 21, 2025

Blog-Post-Header-Image

See the original blog version in English here.

DigitalCredentialsDemo Icon

Want to experience digital credentials in action?

Try Digital Credentials

1. Giới thiệu#

Chứng minh danh tính trực tuyến là một thách thức không ngừng, dẫn đến sự phụ thuộc vào mật khẩu và việc chia sẻ các tài liệu nhạy cảm qua các kênh không an toàn. Điều này đã làm cho quy trình xác minh danh tính của doanh nghiệp trở nên chậm chạp, tốn kém và dễ bị gian lận. Thông tin xác thực kỹ thuật số (Digital Credentials) mang đến một cách tiếp cận mới, trao lại quyền kiểm soát dữ liệu cho người dùng. Chúng là phiên bản kỹ thuật số của một wallet vật lý, chứa mọi thứ từ giấy phép lái xe đến bằng đại học, nhưng có thêm lợi ích là an toàn về mặt mật mã, bảo vệ quyền riêng tư và có thể xác minh ngay lập tức.

Guide này cung cấp cho các nhà phát triển một hướng dẫn thực tế, từng bước để xây dựng một trình xác minh cho Digital Credentials. Mặc dù các tiêu chuẩn đã tồn tại, nhưng có rất ít hướng dẫn về việc triển khai chúng. Hướng dẫn này lấp đầy khoảng trống đó, chỉ cho bạn cách xây dựng một trình xác minh sử dụng API Digital Credential gốc của trình duyệt, OpenID4VP cho giao thức trình bày và ISO mDoc (ví dụ: giấy phép lái xe di động) làm định dạng thông tin xác thực.

Kết quả cuối cùng sẽ là một ứng dụng Next.js đơn giản nhưng đầy đủ chức năng, có thể yêu cầu, nhận và xác minh một Digital Credential từ một wallet di động tương thích.

Dưới đây là cái nhìn nhanh về ứng dụng cuối cùng khi hoạt động. Quá trình này bao gồm bốn bước chính:

Bước 1: Trang ban đầu Người dùng truy cập trang ban đầu và nhấp vào "Xác minh với Digital Identity" để bắt đầu quá trình.

Bước 2: Lời nhắc tin cậy Trình duyệt yêu cầu người dùng xác nhận tin cậy. Người dùng nhấp vào "Tiếp tục" để tiến hành.

Bước 3: Quét mã QR Một mã QR được hiển thị, người dùng quét mã này bằng ứng dụng wallet tương thích của họ.

Bước 4: Thông tin xác thực đã được giải mã Sau khi xác minh thành công, ứng dụng hiển thị dữ liệu thông tin xác thực đã được giải mã.

1.1 Cách hoạt động#

Điều kỳ diệu đằng sau thông tin xác thực kỹ thuật số nằm ở mô hình "tam giác tin cậy" đơn giản nhưng mạnh mẽ, liên quan đến ba bên chính:

  • Bên phát hành (Issuer): Một cơ quan có thẩm quyền đáng tin cậy (ví dụ: một cơ quan chính phủ, trường đại học, hoặc ngân hàng) ký và cấp thông tin xác thực bằng mật mã cho người dùng.
  • Người nắm giữ (Holder): Người dùng, người nhận thông tin xác thực và lưu trữ nó một cách an toàn trong một digital wallet cá nhân trên thiết bị của họ.
  • Bên xác minh (Verifier): Một ứng dụng hoặc dịch vụ cần kiểm tra thông tin xác thực của người dùng.

Khi người dùng muốn truy cập một dịch vụ, họ trình bày thông tin xác thực từ wallet của mình. Bên xác minh sau đó có thể kiểm tra ngay lập tức tính xác thực của nó mà không cần liên hệ trực tiếp với bên phát hành ban đầu.

1.2 Tại sao Trình xác minh lại cần thiết (và Tại sao bạn lại ở đây)#

Để hệ sinh thái danh tính phi tập trung này phát triển mạnh, vai trò của trình xác minh (verifier) là cực kỳ quan trọng. Họ là những người gác cổng của cơ sở hạ tầng tin cậy mới này, là những người sử dụng thông tin xác thực và làm cho chúng trở nên hữu ích trong thế giới thực. Như sơ đồ dưới đây minh họa, một trình xác minh hoàn thành tam giác tin cậy bằng cách yêu cầu, nhận và xác thực thông tin xác thực từ người nắm giữ.

Nếu bạn là một nhà phát triển, việc xây dựng một dịch vụ để thực hiện việc xác minh này là một kỹ năng nền tảng cho thế hệ ứng dụng an toàn và lấy người dùng làm trung tâm tiếp theo. Guide này được thiết kế để hướng dẫn bạn qua chính xác quy trình đó. Chúng ta sẽ đề cập đến mọi thứ bạn cần biết để xây dựng trình xác minh thông tin xác thực có thể xác minh của riêng bạn, từ các khái niệm và tiêu chuẩn cốt lõi đến các chi tiết triển khai từng bước về việc xác thực chữ ký và kiểm tra trạng thái thông tin xác thực.

Bạn muốn bỏ qua phần trước? Bạn có thể tìm thấy dự án hoàn chỉnh cho hướng dẫn này trên GitHub. Hãy thoải mái sao chép nó và tự mình thử nghiệm: https://github.com/corbado/digital-credentials-example

Hãy bắt đầu nào.

2. Các điều kiện tiên quyết để xây dựng Trình xác minh#

Trước khi bắt đầu, hãy đảm bảo bạn có:

  1. Hiểu biết cơ bản về Digital Credentials và mdoc
    • Hướng dẫn này tập trung vào định dạng ISO mDoc (ví dụ: cho giấy phép lái xe di động) và không đề cập đến các định dạng khác như W3C Verifiable Credentials (VCs). Việc quen thuộc với các khái niệm cơ bản của mdoc sẽ rất hữu ích.
  2. Docker và Docker Compose
    • Dự án của chúng ta sử dụng cơ sở dữ liệu MySQL trong một Docker container để quản lý trạng thái phiên OIDC. Hãy đảm bảo bạn đã cài đặt và chạy cả hai.
  3. Giao thức đã chọn: OpenID4VP
    • Chúng ta sẽ sử dụng giao thức OpenID4VP (OpenID for Verifiable Presentations) cho luồng trao đổi thông tin xác thực.
  4. Chuẩn bị Tech Stack
    • Sử dụng TypeScript (Node.js) cho logic backend.
    • Sử dụng Next.js cho cả backend (API routes) và frontend (UI).
    • Các thư viện chính: thư viện giải mã CBOR để phân tích mdoc và một client MySQL.
  5. Thông tin xác thực và Wallet thử nghiệm
    • Chúng ta sẽ sử dụng CMWallet cho Android, một wallet hiểu các yêu cầu OpenID4VP và có thể trình bày thông tin xác thực mdoc.
  6. Kiến thức cơ bản về Mật mã học
    • Hiểu về chữ ký số và các khái niệm khóa công khai/khóa riêng tư liên quan đến mdoc và các luồng OIDC.

Bây giờ chúng ta sẽ đi qua từng điều kiện tiên quyết này một cách chi tiết, bắt đầu với các tiêu chuẩn và giao thức làm nền tảng cho trình xác minh dựa trên mdoc này.

2.1 Lựa chọn Giao thức#

Trình xác minh của chúng ta được xây dựng cho các tiêu chuẩn/giao thức sau:

Tiêu chuẩn / Giao thứcMô tả
W3C VCMô hình Dữ liệu Thông tin xác thực có thể xác minh của W3C. Nó định nghĩa cấu trúc tiêu chuẩn cho thông tin xác thực kỹ thuật số, bao gồm các claim, metadata và bằng chứng.
SD-JWTTiết lộ có chọn lọc cho JWT. Một định dạng cho VC dựa trên JSON Web Tokens cho phép người nắm giữ chỉ tiết lộ có chọn lọc các claim cụ thể từ một thông tin xác thực, tăng cường quyền riêng tư.
ISO mDocISO/IEC 18013-5. Tiêu chuẩn quốc tế cho Giấy phép lái xe di động (mDLs) và các loại ID di động khác, định nghĩa cấu trúc dữ liệu và giao thức truyền thông cho việc sử dụng ngoại tuyến và trực tuyến.
OpenID4VPOpenID for Verifiable Presentations. Một giao thức trình bày có khả năng tương tác được xây dựng trên OAuth 2.0. Nó định nghĩa cách một trình xác minh yêu cầu thông tin xác thực và wallet của người nắm giữ trình bày chúng.

Đối với hướng dẫn này, chúng ta đặc biệt sử dụng:

  • OpenID4VP làm giao thức để yêu cầu và nhận thông tin xác thực.
  • ISO mDoc làm định dạng thông tin xác thực (ví dụ: cho giấy phép lái xe di động).

Lưu ý về phạm vi: Mặc dù chúng ta giới thiệu ngắn gọn về W3C VC và SD-JWT để cung cấp bối cảnh rộng hơn, hướng dẫn này chỉ triển khai thông tin xác thực ISO mDoc qua OpenID4VP. Các VC dựa trên W3C nằm ngoài phạm vi của ví dụ này.

2.1.1 ISO mDoc (Mobile Document)#

Tiêu chuẩn ISO/IEC 18013-5 mDoc định nghĩa cấu trúc và mã hóa cho các tài liệu di động như giấy phép lái xe di động (mDLs). Thông tin xác thực mDoc được mã hóa bằng CBOR, được ký bằng mật mã và có thể được trình bày kỹ thuật số để xác minh. Trình xác minh của chúng ta sẽ tập trung vào việc giải mã và xác thực các thông tin xác thực mdoc này.

2.1.2 OpenID4VP (OpenID for Verifiable Presentations)#

OpenID4VP là một giao thức có khả năng tương tác để yêu cầu và trình bày thông tin xác thực kỹ thuật số, được xây dựng trên OAuth 2.0 và OpenID Connect. Trong triển khai này, OpenID4VP được sử dụng để:

  • Khởi tạo luồng trình bày thông tin xác thực (qua mã QR hoặc API trình duyệt)
  • Nhận thông tin xác thực mdoc từ wallet của người dùng
  • Đảm bảo việc trao đổi thông tin xác thực an toàn, có trạng thái và bảo vệ quyền riêng tư

2.2 Lựa chọn Tech Stack#

Bây giờ chúng ta đã hiểu rõ về các tiêu chuẩn và giao thức, chúng ta cần chọn tech stack phù hợp để xây dựng trình xác minh của mình. Các lựa chọn của chúng ta được thiết kế để đảm bảo sự mạnh mẽ, trải nghiệm nhà phát triển tốt và khả năng tương thích với hệ sinh thái web hiện đại.

2.2.1 Ngôn ngữ: TypeScript#

Chúng ta sẽ sử dụng TypeScript cho cả mã frontend và backend. Là một tập hợp con mở rộng của JavaScript, nó thêm vào kiểu tĩnh, giúp phát hiện lỗi sớm, cải thiện chất lượng mã và làm cho các ứng dụng phức tạp dễ quản lý hơn. Trong bối cảnh nhạy cảm về bảo mật như xác minh thông tin xác thực, an toàn kiểu là một lợi thế lớn.

2.2.2 Framework: Next.js#

Next.js là framework chúng ta lựa chọn vì nó cung cấp một trải nghiệm tích hợp, liền mạch để xây dựng các ứng dụng full-stack.

  • Đối với Frontend: Chúng ta sẽ sử dụng Next.js với React để xây dựng giao diện người dùng nơi quá trình xác minh được khởi tạo (ví dụ: hiển thị mã QR).
  • Đối với Backend: Chúng ta sẽ tận dụng Next.js API Routes để tạo các endpoint phía máy chủ. Các endpoint này chịu trách nhiệm tạo các yêu cầu OpenID4VP hợp lệ và hoạt động như redirect_uri để nhận và xác minh phản hồi cuối cùng từ CMWallet một cách an toàn.

2.2.3 Các thư viện chính#

Việc triển khai của chúng ta dựa vào một bộ thư viện cụ thể cho frontend và backend:

  • next: Framework Next.js, được sử dụng cho cả backend API routes và frontend UI.
  • reactreact-dom: Cung cấp năng lượng cho giao diện người dùng frontend.
  • cbor-web: Được sử dụng để giải mã thông tin xác thực mdoc được mã hóa bằng CBOR thành các đối tượng JavaScript có thể sử dụng được.
  • mysql2: Cung cấp kết nối cơ sở dữ liệu MySQL để lưu trữ các challenge và phiên xác minh.
  • uuid: Một thư viện để tạo các chuỗi challenge (nonces) duy nhất.
  • @types/uuid: Các kiểu TypeScript để tạo UUID.

Lưu ý về openid-client: Các trình xác minh cấp sản xuất, tiên tiến hơn có thể sử dụng thư viện openid-client để xử lý trực tiếp giao thức OpenID4VP trên backend, cho phép các tính năng như redirect_uri động. Trong một luồng OpenID4VP do máy chủ điều khiển với redirect_uri, openid-client sẽ được sử dụng để phân tích và xác thực trực tiếp các phản hồi vp_token. Đối với hướng dẫn này, chúng ta đang sử dụng một luồng đơn giản hơn, qua trung gian trình duyệt mà không yêu cầu nó, làm cho quá trình dễ hiểu hơn.

Tech stack này đảm bảo một triển khai trình xác minh mạnh mẽ, an toàn về kiểu và có khả năng mở rộng, tập trung vào API Digital Credential của trình duyệt và định dạng thông tin xác thực ISO mDoc.

2.3 Lấy Wallet và Thông tin xác thực thử nghiệm#

Để kiểm tra trình xác minh của bạn, bạn cần một wallet di động có thể tương tác với API Digital Credential của trình duyệt.

Chúng ta sẽ sử dụng CMWallet, một wallet thử nghiệm mạnh mẽ, tuân thủ OpenID4VP cho Android.

Cách cài đặt CMWallet (Android):

  1. Tải xuống tệp APK bằng liên kết ở trên trực tiếp trên thiết bị Android của bạn.
  2. Mở Cài đặt > Bảo mật trên thiết bị của bạn.
  3. Bật "Cài đặt ứng dụng không rõ nguồn gốc" cho trình duyệt bạn đã sử dụng để tải xuống tệp.
  4. Tìm tệp APK đã tải xuống trong thư mục "Tải xuống" của bạn và nhấn vào nó để bắt đầu cài đặt.
  5. Làm theo các hướng dẫn trên màn hình để hoàn tất cài đặt.
  6. Mở CMWallet, và bạn sẽ thấy nó đã được tải sẵn các thông tin xác thực thử nghiệm, sẵn sàng cho luồng xác minh.

Lưu ý: Chỉ cài đặt các tệp APK từ các nguồn bạn tin cậy. Liên kết được cung cấp là từ kho lưu trữ dự án chính thức.

2.4 Kiến thức về Mật mã học#

Trước khi chúng ta đi sâu vào việc triển khai, điều cần thiết là phải hiểu các khái niệm mật mã học làm nền tảng cho thông tin xác thực có thể xác minh. Đây là điều làm cho chúng "có thể xác minh" và đáng tin cậy.

2.4.1 Chữ ký số: Nền tảng của sự tin cậy#

Về cơ bản, một Verifiable Credential là một tập hợp các claim (như tên, ngày sinh, v.v.) đã được ký điện tử bởi một bên phát hành. Một chữ ký số cung cấp hai đảm bảo quan trọng:

  • Tính xác thực: Nó chứng minh rằng thông tin xác thực thực sự được tạo ra bởi bên phát hành chứ không phải bởi một kẻ mạo danh.
  • Tính toàn vẹn: Nó chứng minh rằng thông tin xác thực đã không bị thay đổi hoặc giả mạo kể từ khi nó được ký.

2.4.2 Mật mã hóa khóa công khai/khóa riêng tư#

Chữ ký số được tạo bằng mật mã hóa khóa công khai/khóa riêng tư (còn gọi là mật mã hóa bất đối xứng). Đây là cách nó hoạt động trong bối cảnh của chúng ta:

  1. Bên phát hành có một cặp khóa: một khóa riêng tư, được giữ bí mật, và một khóa công khai, được cung cấp cho mọi người (thường qua DID Document của họ).
  2. Ký: Khi một bên phát hành tạo ra một thông tin xác thực, họ sử dụng khóa riêng tư của mình để tạo ra một chữ ký số duy nhất cho dữ liệu thông tin xác thực cụ thể đó.
  3. Xác minh: Khi trình xác minh của chúng ta nhận được thông tin xác thực, nó sử dụng khóa công khai của bên phát hành để kiểm tra chữ ký. Nếu kiểm tra thành công, trình xác minh biết rằng thông tin xác thực là xác thực và không bị giả mạo. Bất kỳ thay đổi nào đối với dữ liệu thông tin xác thực sẽ làm cho chữ ký không hợp lệ.

Lưu ý về DID: Trong hướng dẫn này, chúng ta không giải quyết các khóa của bên phát hành thông qua DID. Trong môi trường sản xuất, các bên phát hành thường sẽ công khai các khóa công khai của họ qua DID hoặc các điểm cuối có thẩm quyền khác, mà trình xác minh sẽ sử dụng để xác thực mật mã.

2.4.3 Verifiable Credentials dưới dạng JWT#

Verifiable Credentials thường được định dạng dưới dạng JSON Web Tokens (JWTs). Một JWT là một cách nhỏ gọn, an toàn cho URL để biểu diễn các claim được chuyển giữa hai bên. Một JWT đã ký (còn được gọi là JWS) có ba phần được phân tách bằng dấu chấm (.):

  • Header: Chứa metadata về token, như thuật toán ký được sử dụng (alg).
  • Payload: Chứa các claim thực tế của Verifiable Credential (vc claim), bao gồm issuer, credentialSubject, v.v.
  • Signature: Chữ ký số được tạo bởi bên phát hành, bao gồm cả header và payload.
// Ví dụ về cấu trúc JWT [Header].[Payload].[Signature]

Lưu ý: Verifiable Credentials dựa trên JWT nằm ngoài phạm vi của bài đăng blog này. Việc triển khai này tập trung vào thông tin xác thực ISO mDoc và OpenID4VP, không phải W3C Verifiable Credentials hay thông tin xác thực dựa trên JWT.

2.4.4 Verifiable Presentation: Chứng minh quyền sở hữu#

Việc một trình xác minh biết rằng một thông tin xác thực là hợp lệ là chưa đủ; nó cũng cần biết rằng người trình bày thông tin xác thực là người nắm giữ hợp pháp. Điều này ngăn chặn ai đó sử dụng một thông tin xác thực bị đánh cắp.

Điều này được giải quyết bằng cách sử dụng Verifiable Presentation (VP). Một VP là một lớp bọc xung quanh một hoặc nhiều VC được ký bởi chính người nắm giữ.

Luồng diễn ra như sau:

  1. Trình xác minh yêu cầu người dùng trình bày một thông tin xác thực.
  2. Wallet của người dùng tạo ra một Verifiable Presentation, gói (các) thông tin xác thực cần thiết vào bên trong nó, và ký toàn bộ bản trình bày bằng khóa riêng tư của người nắm giữ.
  3. Wallet gửi VP đã ký này đến trình xác minh.

Trình xác minh của chúng ta sau đó phải thực hiện hai lần kiểm tra chữ ký riêng biệt:

  1. Xác minh (các) Credential: Kiểm tra chữ ký trên mỗi VC bên trong bản trình bày bằng khóa công khai của bên phát hành. (Chứng minh thông tin xác thực là thật).
  2. Xác minh Presentation: Kiểm tra chữ ký trên chính VP bằng khóa công khai của người nắm giữ. (Chứng minh người trình bày nó là chủ sở hữu).

Việc kiểm tra hai cấp độ này đảm bảo cả tính xác thực của thông tin xác thực và danh tính của người trình bày nó, tạo ra một mô hình tin cậy mạnh mẽ và an toàn.

Lưu ý: Khái niệm Verifiable Presentations như được định nghĩa trong hệ sinh thái W3C VC nằm ngoài phạm vi của bài đăng blog này. Thuật ngữ Verifiable Presentation ở đây đề cập đến phản hồi vp_token của OpenID4VP, hoạt động tương tự như một W3C VP nhưng dựa trên ngữ nghĩa của ISO mDoc thay vì mô hình chữ ký JSON-LD của W3C. Guide này tập trung vào thông tin xác thực ISO mDoc và OpenID4VP, không phải W3C Verifiable Presentations hay việc xác thực chữ ký của chúng.

3. Tổng quan về kiến trúc#

Kiến trúc trình xác minh của chúng ta sử dụng API Digital Credential tích hợp của trình duyệt làm trung gian an toàn để kết nối ứng dụng web của chúng ta với CMWallet di động của người dùng. Cách tiếp cận này đơn giản hóa luồng bằng cách để trình duyệt xử lý việc hiển thị mã QR gốc và giao tiếp với wallet.

  • Frontend (Next.js & React): Một trang web nhẹ hướng tới người dùng. Công việc của nó là lấy một đối tượng yêu cầu từ backend của chúng ta, chuyển nó đến API navigator.credentials.get() của trình duyệt, nhận kết quả và chuyển tiếp nó đến backend để xác minh.
  • Backend (Next.js API Routes): Trung tâm xử lý của trình xác minh. Nó tạo ra một đối tượng yêu cầu hợp lệ cho API trình duyệt và cung cấp một endpoint để nhận bản trình bày thông tin xác thực từ frontend để xác thực cuối cùng.
  • Trình duyệt (Credential API): Người điều phối. Nó nhận đối tượng yêu cầu từ frontend của chúng ta, hiểu giao thức openid4vp và tự động tạo mã QR. Sau đó, nó chờ wallet trả về một phản hồi.
  • CMWallet (Ứng dụng di động): Wallet của người dùng. Nó quét mã QR, xử lý yêu cầu, nhận được sự đồng ý của người dùng và gửi phản hồi đã ký trở lại trình duyệt.

Dưới đây là một sơ đồ tuần tự minh họa luồng hoàn chỉnh và chính xác:

Giải thích luồng:

  1. Khởi tạo: Người dùng nhấp vào nút "Xác minh" trên Frontend của chúng ta.
  2. Đối tượng yêu cầu: Frontend gọi đến Backend của chúng ta (/api/verify/start), backend này tạo một đối tượng yêu cầu chứa truy vấn và một nonce, sau đó trả về nó.
  3. Gọi API trình duyệt: Frontend gọi navigator.credentials.get() với đối tượng yêu cầu.
  4. Mã QR gốc: Trình duyệt thấy yêu cầu giao thức openid4vp và tự động hiển thị một mã QR. Lời hứa (promise) .get() bây giờ đang ở trạng thái chờ.

Lưu ý: Luồng mã QR này xảy ra trên các trình duyệt máy tính để bàn. Trên các trình duyệt di động (Android Chrome với cờ thử nghiệm được bật), trình duyệt có thể giao tiếp trực tiếp với các wallet tương thích trên cùng một thiết bị, loại bỏ nhu cầu quét mã QR. Để bật tính năng này trên Android Chrome, hãy điều hướng đến chrome://flags#web-identity-digital-credentials và đặt cờ thành "Enabled".

  1. Quét & Trình bày: Người dùng quét mã QR bằng CMWallet. Wallet nhận được sự chấp thuận của người dùng và gửi Verifiable Presentation trở lại trình duyệt.
  2. Promise được giải quyết: Trình duyệt nhận được phản hồi, và lời hứa .get() ban đầu trên frontend cuối cùng được giải quyết, cung cấp payload của bản trình bày.
  3. Xác minh Backend: Frontend gửi POST payload của bản trình bày đến endpoint /api/verify/finish của backend. Backend xác thực nonce và thông tin xác thực.
  4. Kết quả: Backend trả về một thông báo thành công hoặc thất bại cuối cùng cho frontend, frontend này sẽ cập nhật giao diện người dùng.

4. Xây dựng Trình xác minh#

Bây giờ chúng ta đã hiểu rõ về các tiêu chuẩn, giao thức và luồng kiến trúc, chúng ta có thể bắt đầu xây dựng trình xác minh của mình.

Làm theo hoặc sử dụng mã nguồn cuối cùng

Bây giờ chúng ta sẽ đi qua từng bước thiết lập và triển khai mã. Nếu bạn muốn chuyển thẳng đến sản phẩm hoàn chỉnh, bạn có thể sao chép dự án hoàn chỉnh từ kho lưu trữ GitHub của chúng tôi và chạy nó cục bộ.

git clone https://github.com/corbado/digital-credentials-example.git

4.1 Thiết lập dự án#

Đầu tiên, chúng ta sẽ khởi tạo một dự án Next.js mới, cài đặt các phụ thuộc cần thiết và khởi động cơ sở dữ liệu của chúng ta.

4.1.1 Khởi tạo ứng dụng Next.js#

Mở terminal của bạn, điều hướng đến thư mục bạn muốn tạo dự án và chạy lệnh sau. Chúng ta đang sử dụng App Router, TypeScript và Tailwind CSS cho dự án này.

npx create-next-app@latest . --ts --eslint --tailwind --app --src-dir --import-alias "@/*" --use-npm

Lệnh này tạo một ứng dụng Next.js mới trong thư mục hiện tại của bạn.

4.1.2 Cài đặt các phụ thuộc#

Tiếp theo, chúng ta cần cài đặt các thư viện sẽ xử lý việc giải mã CBOR, kết nối cơ sở dữ liệu và tạo UUID.

npm install cbor-web mysql2 uuid @types/uuid

Lệnh này cài đặt:

  • cbor-web: Để giải mã payload thông tin xác thực mdoc.
  • mysql2: Client MySQL cho cơ sở dữ liệu của chúng ta.
  • uuid: Để tạo các chuỗi challenge duy nhất.
  • @types/uuid: Các kiểu TypeScript cho thư viện uuid.

4.1.3 Khởi động cơ sở dữ liệu#

Backend của chúng ta yêu cầu một cơ sở dữ liệu MySQL để lưu trữ dữ liệu phiên OIDC, đảm bảo rằng mỗi luồng xác minh đều an toàn và có trạng thái. Chúng ta đã bao gồm một tệp docker-compose.yml để làm cho việc này trở nên dễ dàng.

Nếu bạn đã sao chép kho lưu trữ, bạn chỉ cần chạy docker-compose up -d. Nếu bạn đang xây dựng từ đầu, hãy tạo một tệp có tên docker-compose.yml với nội dung sau:

services: mysql: image: mysql:8.0 restart: always environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: digital_credentials MYSQL_USER: app_user MYSQL_PASSWORD: app_password ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 volumes: mysql_data:

Thiết lập Docker Compose này cũng yêu cầu một kịch bản khởi tạo SQL. Tạo một thư mục có tên sql và bên trong nó, một tệp có tên init.sql với nội dung sau để thiết lập các bảng cần thiết:

-- Create database if not exists CREATE DATABASE IF NOT EXISTS digital_credentials; USE digital_credentials; -- Table for storing challenges CREATE TABLE IF NOT EXISTS challenges ( id VARCHAR(36) PRIMARY KEY, challenge VARCHAR(255) NOT NULL UNIQUE, expires_at TIMESTAMP NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, used BOOLEAN DEFAULT FALSE, INDEX idx_challenge (challenge), INDEX idx_expires_at (expires_at) ); -- Table for storing verification sessions CREATE TABLE IF NOT EXISTS verification_sessions ( id VARCHAR(36) PRIMARY KEY, challenge_id VARCHAR(36), status ENUM('pending', 'verified', 'failed', 'expired') DEFAULT 'pending', presentation_data JSON, verified_at TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (challenge_id) REFERENCES challenges(id) ON DELETE CASCADE, INDEX idx_challenge_id (challenge_id), INDEX idx_status (status) ); -- Table for storing verified credentials data (optional) CREATE TABLE IF NOT EXISTS verified_credentials ( id VARCHAR(36) PRIMARY KEY, session_id VARCHAR(36), credential_type VARCHAR(255), issuer VARCHAR(255), subject VARCHAR(255), claims JSON, verified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (session_id) REFERENCES verification_sessions(id) ON DELETE CASCADE, INDEX idx_session_id (session_id), INDEX idx_credential_type (credential_type) );

Khi cả hai tệp đã ở đúng vị trí, hãy mở terminal của bạn trong thư mục gốc của dự án và chạy:

docker-compose up -d

Lệnh này sẽ khởi động một container MySQL trong nền.

4.2 Tổng quan về kiến trúc của ứng dụng Next.js#

Ứng dụng Next.js của chúng ta được cấu trúc để tách biệt các mối quan tâm giữa frontend và backend, mặc dù chúng là một phần của cùng một dự án.

  • Frontend (src/app/page.tsx): Một trang React duy nhất khởi tạo luồng xác minh và hiển thị kết quả. Nó tương tác với API Digital Credential của trình duyệt.
  • Backend API Routes (src/app/api/verify/...):
    • start/route.ts: Tạo yêu cầu OpenID4VP và một nonce bảo mật.
    • finish/route.ts: Nhận bản trình bày từ wallet (qua trình duyệt), xác thực nonce và giải mã thông tin xác thực.
  • Thư viện (src/lib/):
    • database.ts: Quản lý tất cả các tương tác cơ sở dữ liệu (tạo challenge, xác minh phiên).
    • crypto.ts: Xử lý việc giải mã thông tin xác thực mDoc dựa trên CBOR.

Dưới đây là một sơ đồ minh họa kiến trúc nội bộ:

4.3 Xây dựng Frontend#

Frontend của chúng ta được cố ý làm nhẹ. Trách nhiệm chính của nó là hoạt động như một trình kích hoạt hướng tới người dùng cho luồng xác minh và giao tiếp với cả backend của chúng ta và khả năng xử lý thông tin xác thực gốc của trình duyệt. Nó không chứa bất kỳ logic giao thức phức tạp nào; tất cả đều được ủy quyền.

Cụ thể, frontend sẽ xử lý những việc sau:

  • Tương tác người dùng: Cung cấp một giao diện đơn giản, như nút "Xác minh", để người dùng bắt đầu quá trình.
  • Quản lý trạng thái: Quản lý trạng thái giao diện người dùng, hiển thị chỉ báo tải trong khi quá trình xác minh đang diễn ra và hiển thị thông báo thành công hoặc lỗi cuối cùng.
  • Giao tiếp Backend (Yêu cầu): Gọi /api/verify/start và nhận một payload JSON có cấu trúc (protocol, request, state) mô tả chính xác những gì wallet nên trình bày.
  • Gọi API trình duyệt: Giao đối tượng JSON đó cho navigator.credentials.get(), đối tượng này sẽ hiển thị một mã QR gốc và chờ phản hồi của wallet.
  • Giao tiếp Backend (Phản hồi): Khi API trình duyệt trả về Verifiable Presentation, nó sẽ gửi dữ liệu này đến endpoint /api/verify/finish của chúng ta trong một yêu cầu POST để xác thực cuối cùng phía máy chủ.
  • Hiển thị kết quả: Cập nhật giao diện người dùng để thông báo cho người dùng biết liệu việc xác minh có thành công hay thất bại, dựa trên phản hồi từ backend.

Logic cốt lõi nằm trong hàm startVerification:

// src/app/page.tsx const startVerification = async () => { setLoading(true); setVerificationResult(null); try { // 1. Check if the browser supports the API if (!navigator.credentials?.get) { throw new Error("Browser does not support the Credential API."); } // 2. Ask our backend for a request object const res = await fetch("/api/verify/start"); const { protocol, request } = await res.json(); // 3. Hand that object to the browser – this triggers the native QR code const credential = await (navigator.credentials as any).get({ mediation: "required", digital: { requests: [ { protocol, // "openid4vp" data: request, // contains dcql_query, nonce, etc. }, ], }, }); // 4. Forward the wallet response (from the browser) to our finish endpoint for server-side checks const verifyRes = await fetch("/api/verify/finish", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(credential), }); const result = await verifyRes.json(); if (verifyRes.ok && result.verified) { setVerificationResult(`Success: ${result.message}`); } else { throw new Error(result.message || "Verification failed."); } } catch (err) { setVerificationResult(`Error: ${(err as Error).message}`); } finally { setLoading(false); } };

Hàm này cho thấy bốn bước chính của logic frontend: kiểm tra hỗ trợ API, lấy yêu cầu từ backend, gọi API trình duyệt và gửi kết quả trở lại để xác minh. Phần còn lại của tệp là boilerplate React tiêu chuẩn để quản lý trạng thái và hiển thị giao diện người dùng, bạn có thể xem trong kho lưu trữ GitHub.

Tại sao lại là digitalmediation: 'required'?#

Bạn có thể nhận thấy lệnh gọi navigator.credentials.get() của chúng ta trông khác với các ví dụ đơn giản hơn. Điều này là do chúng ta tuân thủ nghiêm ngặt đặc tả W3C Digital Credentials API chính thức.

  • Thành viên digital: Đặc tả yêu cầu tất cả các yêu cầu thông tin xác thực kỹ thuật số phải được lồng bên trong một đối tượng digital. Điều này cung cấp một không gian tên rõ ràng, được tiêu chuẩn hóa cho API này, phân biệt nó với các loại thông tin xác thực khác (như password hoặc federated) và cho phép các phần mở rộng trong tương lai mà không có xung đột.

  • mediation: 'required': Tùy chọn này là một tính năng bảo mật và trải nghiệm người dùng quan trọng. Nó bắt buộc người dùng phải tương tác tích cực với một lời nhắc (ví dụ: quét sinh trắc học, nhập mã PIN hoặc màn hình đồng ý) để phê duyệt yêu cầu thông tin xác thực. Nếu không có nó, một trang web có thể cố gắng truy cập thông tin xác thực một cách âm thầm trong nền, điều này gây ra rủi ro riêng tư đáng kể. Bằng cách yêu cầu mediation, chúng ta đảm bảo rằng người dùng luôn kiểm soát và đưa ra sự đồng ý rõ ràng cho mỗi giao dịch.

4.4 Xây dựng các Endpoint Backend#

Với giao diện người dùng React đã sẵn sàng, bây giờ chúng ta cần hai API route thực hiện công việc nặng nhọc trên máy chủ:

  1. /api/verify/start – xây dựng một yêu cầu OpenID4VP, lưu trữ một challenge sử dụng một lần trong MySQL và giao mọi thứ lại cho trình duyệt.
  2. /api/verify/finish – nhận phản hồi từ wallet, xác thực challenge, xác minh & giải mã thông tin xác thực, và cuối cùng trả về một kết quả JSON ngắn gọn cho giao diện người dùng.

4.4.1 /api/verify/start: Tạo yêu cầu OpenID4VP#

// src/app/api/verify/start/route.ts import { NextResponse } from "next/server"; import { v4 as uuidv4 } from "uuid"; import { createChallenge, cleanupExpiredChallenges } from "@/lib/database"; export async function GET() { // 1️⃣ Create a short-lived, random nonce (challenge) const challenge = uuidv4(); const challengeId = uuidv4(); const expiresAt = new Date(Date.now() + 5 * 60 * 1000); await createChallenge(challengeId, challenge, expiresAt); cleanupExpiredChallenges().catch(console.error); // 2️⃣ Build a DCQL query that describes *what* we want const dcqlQuery = { credentials: [ { id: "cred1", format: "mso_mdoc", meta: { doctype_value: "eu.europa.ec.eudi.pid.1" }, claims: [ { path: ["eu.europa.ec.eudi.pid.1", "family_name"] }, { path: ["eu.europa.ec.eudi.pid.1", "given_name"] }, { path: ["eu.europa.ec.eudi.pid.1", "birth_date"] }, ], }, ], }; // 3️⃣ Return an object the browser can pass to navigator.credentials.get() return NextResponse.json({ protocol: "openid4vp", // tells the browser which wallet protocol to use request: { dcql_query: dcqlQuery, // WHAT to present nonce: challenge, // anti-replay response_type: "vp_token", response_mode: "dc_api", // the wallet will POST directly to /finish }, state: { credential_type: "mso_mdoc", // kept for later checks nonce: challenge, challenge_id: challengeId, }, }); }

Các tham số chính

noncethử thách mật mã liên kết yêu cầu & phản hồi (ngăn chặn tấn công phát lại). • dcql_query – Một đối tượng mô tả chính xác các claim chúng ta cần. Đối với guide này, chúng ta sử dụng cấu trúc dcql_query lấy cảm hứng từ các bản nháp gần đây của Digital Credential Query Language, mặc dù đây chưa phải là một tiêu chuẩn hoàn thiện. • state – JSON tùy ý được wallet phản hồi lại để chúng ta có thể tra cứu bản ghi trong DB.

4.4.2 Các hàm trợ giúp cơ sở dữ liệu#

Tệp src/lib/database.ts bao bọc các hoạt động MySQL cơ bản cho các challenge & phiên xác minh (chèn, đọc, đánh dấu đã sử dụng). Việc giữ logic này trong một module duy nhất giúp dễ dàng thay đổi kho dữ liệu sau này.


4.5 /api/verify/finish: Xác thực & Giải mã Presentation#

// src/app/api/verify/finish/route.ts import { NextResponse, NextRequest } from "next/server"; import { v4 as uuidv4 } from "uuid"; import { getChallenge, markChallengeAsUsed, createVerificationSession, updateVerificationSession, } from "@/lib/database"; import { decodeDigitalCredential, decodeAllNamespaces } from "@/lib/crypto"; export async function POST(request: NextRequest) { const body = await request.json(); // 1️⃣ Extract the verifiable presentation pieces const vpTokenMap = body.vp_token ?? body.data?.vp_token; const state = body.state; const mdocToken = vpTokenMap?.cred1; // we asked for this ID in dcqlQuery if (!vpTokenMap || !state || !mdocToken) { return NextResponse.json( { verified: false, message: "Malformed response" }, { status: 400 }, ); } // 2️⃣ One-time-use challenge validation const stored = await getChallenge(state.nonce); if (!stored) { return NextResponse.json( { verified: false, message: "Invalid or expired challenge" }, { status: 400 }, ); } const sessionId = uuidv4(); await createVerificationSession(sessionId, stored.id); // 3️⃣ (Pseudo) cryptographic checks – replace with real mDL validation in prod // In a real application, you would use a dedicated library to perform full // cryptographic validation of the mdoc signature against the issuer's public key. const isValid = mdocToken.length > 0; if (!isValid) { await updateVerificationSession(sessionId, "failed", { reason: "mdoc validation failed", }); return NextResponse.json( { verified: false, message: "Credential validation failed" }, { status: 400 }, ); } // 4️⃣ Decode the mobile-DL (mdoc) payload into human readable JSON const decoded = await decodeDigitalCredential(mdocToken); const readable = decodeAllNamespaces(decoded)["eu.europa.ec.eudi.pid.1"]; await markChallengeAsUsed(state.nonce); await updateVerificationSession(sessionId, "verified", { readable }); return NextResponse.json({ verified: true, message: "mdoc credential verified successfully!", credentialData: readable, sessionId, }); }

Các trường quan trọng trong phản hồi của wallet

vp_token – map chứa mỗi thông tin xác thực mà wallet trả về. Đối với demo của chúng ta, chúng ta lấy vp_token.cred1. • state – bản sao của blob chúng ta đã cung cấp trong /start; chứa nonce để chúng ta có thể tra cứu bản ghi trong DB. • mdocToken – một cấu trúc CBOR được mã hóa Base64URL đại diện cho ISO mDoc.

4.6 Giải mã thông tin xác thực mdoc#

Khi trình xác minh nhận được một thông tin xác thực mdoc từ trình duyệt, nó là một chuỗi Base64URL chứa dữ liệu nhị phân được mã hóa CBOR. Để trích xuất các claim thực tế, endpoint finish thực hiện một quy trình giải mã nhiều bước bằng cách sử dụng các hàm trợ giúp từ src/lib/crypto.ts.

4.6.1 Bước 1: Giải mã Base64URL và CBOR#

Hàm decodeDigitalCredential xử lý việc chuyển đổi từ chuỗi đã mã hóa sang một đối tượng có thể sử dụng được:

// src/lib/crypto.ts export async function decodeDigitalCredential(encodedCredential: string) { // 1. Convert Base64URL to standard Base64 const base64UrlToBase64 = (input: string) => { let base64 = input.replace(/-/g, "+").replace(/_/g, "/"); const pad = base64.length % 4; if (pad) base64 += "=".repeat(4 - pad); return base64; }; const base64 = base64UrlToBase64(encodedCredential); // 2. Decode Base64 to binary const binaryString = atob(base64); const byteArray = Uint8Array.from(binaryString, (char) => char.charCodeAt(0)); // 3. Decode CBOR const decoded = await cbor.decodeFirst(byteArray); return decoded; }
  • Base64URL sang Base64: Chuyển đổi thông tin xác thực từ mã hóa Base64URL sang mã hóa Base64 tiêu chuẩn.
  • Base64 sang Nhị phân: Giải mã chuỗi Base64 thành một mảng byte nhị phân.
  • Giải mã CBOR: Sử dụng thư viện cbor-web để giải mã dữ liệu nhị phân thành một đối tượng JavaScript có cấu trúc.

4.6.2 Bước 2: Trích xuất các Claim theo Namespace#

Hàm decodeAllNamespaces xử lý thêm đối tượng CBOR đã giải mã để trích xuất các claim thực tế từ các namespace liên quan:

// src/lib/crypto.ts export function decodeAllNamespaces(jsonObj) { const decoded = {}; try { jsonObj.documents.forEach((doc, idx) => { // 1) issuerSigned.nameSpaces: const issuerNS = doc.issuerSigned?.nameSpaces || {}; Object.entries(issuerNS).forEach(([nsName, entries]) => { if (!decoded[nsName]) decoded[nsName] = {}; (entries as any[]).forEach((entry) => { const bytes = Uint8Array.from(entry.value); const decodedEntry = cbor.decodeFirstSync(bytes); Object.assign(decoded[nsName], decodedEntry); }); }); // 2) deviceSigned.nameSpaces (if present): const deviceNS = doc.deviceSigned?.nameSpaces; if (deviceNS?.value?.data) { const bytes = Uint8Array.from(deviceNS.value); decoded[`deviceSigned_ns_${idx}`] = cbor.decodeFirstSync(bytes); } }); } catch (e) { console.error(e); } return decoded; }
  • Lặp qua tất cả các tài liệu trong thông tin xác thực đã giải mã.
  • Giải mã mỗi namespace (ví dụ: eu.europa.ec.eudi.pid.1) để trích xuất các giá trị claim thực tế (như tên, ngày sinh, v.v.).
  • Xử lý cả các namespace do bên phát hành ký và do thiết bị ký nếu có.

Ví dụ đầu ra#

Sau khi chạy qua các bước này, endpoint finish thu được một đối tượng có thể đọc được chứa các claim từ mdoc, ví dụ:

{ "family_name": "Doe", "given_name": "John", "birth_date": "1990-01-01" }

Quá trình này đảm bảo rằng trình xác minh có thể trích xuất thông tin cần thiết từ thông tin xác thực mdoc một cách an toàn và đáng tin cậy để hiển thị và xử lý thêm.

4.7 Hiển thị kết quả trên giao diện người dùng#

Endpoint finish trả về một đối tượng JSON tối thiểu cho frontend:

{ "verified": true, "message": "mdoc credential verified successfully!", "credentialData": { "family_name": "Doe", "given_name": "John", "birth_date": "1990-01-01" } }

Frontend nhận phản hồi này trong startVerification() và chỉ cần lưu nó vào trạng thái React để chúng ta có thể hiển thị một thẻ xác nhận đẹp mắt hoặc hiển thị các claim riêng lẻ – ví dụ: “Chào mừng, John Doe (sinh ngày 1990-01-01)!”.

5. Chạy Trình xác minh và các bước tiếp theo#

Bây giờ bạn đã có một trình xác minh hoàn chỉnh, hoạt động, sử dụng khả năng xử lý thông tin xác thực gốc của trình duyệt. Dưới đây là cách chạy nó cục bộ và những gì bạn có thể làm để đưa nó từ một bằng chứng khái niệm (proof-of-concept) thành một ứng dụng sẵn sàng cho môi trường sản xuất.

5.1 Cách chạy ví dụ#

  1. Sao chép Kho lưu trữ:

    git clone https://github.com/corbado/digital-credentials-example.git cd digital-credentials-example
  2. Cài đặt các phụ thuộc:

    npm install
  3. Khởi động Cơ sở dữ liệu: Đảm bảo Docker đang chạy trên máy của bạn, sau đó khởi động container MySQL:

    docker-compose up -d
  4. Chạy ứng dụng:

    npm run dev

    Mở trình duyệt của bạn đến http://localhost:3000, và bạn sẽ thấy giao diện người dùng của trình xác minh. Bây giờ bạn có thể sử dụng CMWallet của mình để quét mã QR và hoàn thành luồng xác minh.

5.2 Các bước tiếp theo: Từ Demo đến Sản xuất#

Hướng dẫn này cung cấp các khối xây dựng nền tảng cho một trình xác minh. Để làm cho nó sẵn sàng cho môi trường sản xuất, bạn cần triển khai một số tính năng bổ sung:

  • Xác thực mật mã đầy đủ: Triển khai hiện tại sử dụng một kiểm tra giữ chỗ (mdocToken.length > 0). Trong một kịch bản thực tế, bạn phải thực hiện xác thực mật mã đầy đủ của chữ ký mdoc đối với khóa công khai của bên phát hành (ví dụ: bằng cách giải quyết DID của họ hoặc lấy chứng chỉ khóa công khai của họ). Để biết các tiêu chuẩn giải quyết DID, hãy tham khảo đặc tả W3C DID Resolution.

  • Kiểm tra thu hồi của bên phát hành: Thông tin xác thực có thể bị bên phát hành thu hồi trước ngày hết hạn. Một trình xác minh sản xuất phải kiểm tra trạng thái của thông tin xác thực bằng cách truy vấn danh sách thu hồi hoặc endpoint trạng thái do bên phát hành cung cấp. Danh sách trạng thái Verifiable Credentials của W3C cung cấp tiêu chuẩn cho danh sách thu hồi thông tin xác thực.

  • Xử lý lỗi & Bảo mật mạnh mẽ: Thêm xử lý lỗi toàn diện, xác thực đầu vào, giới hạn tốc độ trên các endpoint API và đảm bảo tất cả giao tiếp đều qua HTTPS (TLS) để bảo vệ dữ liệu khi truyền. Hướng dẫn bảo mật API của OWASP cung cấp các phương pháp tốt nhất về bảo mật API toàn diện.

  • Hỗ trợ nhiều loại thông tin xác thực: Mở rộng logic để xử lý các giá trị doctype và định dạng thông tin xác thực khác nhau nếu bạn dự kiến sẽ nhận được nhiều hơn chỉ thông tin xác thực PID của Digital Identity Châu Âu (EUDI). Mô hình dữ liệu Verifiable Credentials của W3C cung cấp các đặc tả định dạng VC toàn diện.

5.3 Những gì nằm ngoài phạm vi của Hướng dẫn này#

Ví dụ này được cố ý tập trung vào luồng cốt lõi qua trung gian trình duyệt để làm cho nó dễ hiểu. Các chủ đề sau được coi là nằm ngoài phạm vi:

  • Bảo mật sẵn sàng cho môi trường sản xuất: Trình xác minh này dành cho mục đích giáo dục và thiếu sự củng cố cần thiết cho một môi trường trực tiếp.
  • W3C Verifiable Credentials: Hướng dẫn này chỉ tập trung vào định dạng ISO mDoc cho giấy phép lái xe di động. Nó không đề cập đến các định dạng phổ biến khác như JWT-VCs hoặc VCs với Linked Data Proofs (LD-Proofs).
  • Các luồng OpenID4VP nâng cao: Chúng ta không triển khai các tính năng OpenID4VP phức tạp hơn, chẳng hạn như giao tiếp trực tiếp từ wallet đến backend bằng redirect_uri hoặc đăng ký client động.

Bằng cách xây dựng trên nền tảng này và kết hợp các bước tiếp theo này, bạn có thể phát triển một trình xác minh mạnh mẽ và an toàn, có khả năng tin cậy và xác thực thông tin xác thực kỹ thuật số trong các ứng dụng của riêng bạn.

Kết luận#

Vậy là xong! Với ít hơn 250 dòng TypeScript, bây giờ chúng ta có một trình xác minh end-to-end có thể:

  1. Công bố một yêu cầu cho API thông tin xác thực của trình duyệt.
  2. Cho phép bất kỳ wallet tuân thủ nào cung cấp một Verifiable Presentation.
  3. Xác thực bản trình bày trên máy chủ.
  4. Cập nhật giao diện người dùng trong thời gian thực.

Trong môi trường sản xuất, bạn sẽ thay thế việc xác thực giữ chỗ bằng các kiểm tra ISO 18013-5 đầy đủ, thêm tra cứu thu hồi của bên phát hành, giới hạn tốc độ, ghi nhật ký kiểm toán, và tất nhiên là TLS end-to-end—nhưng các khối xây dựng cốt lõi vẫn giữ nguyên.

Tài liệu tham khảo#

Dưới đây là một số tài liệu, đặc tả và công cụ chính được sử dụng hoặc tham chiếu trong hướng dẫn này:

Add passkeys to your app in <1 hour with our UI components, SDKs & guides.

Start Free Trial

Share this article


LinkedInTwitterFacebook

Table of Contents