---
url: 'https://www.corbado.com/vi/blog/trien-khai-webauthn-server'
title: 'So sánh 9 thư viện triển khai WebAuthn Server'
description: 'Bài viết này giúp bạn tìm thư viện WebAuthn server phù hợp để cung cấp passkey. So sánh 9 thư viện và đưa ra chiến lược để chọn thư viện phù hợp.'
lang: 'vi'
author: 'Nicolai'
date: '2026-07-27T08:26:36.856Z'
lastModified: '2026-07-27T08:27:38.242Z'
keywords: 'triển khai webauthn server, thư viện webauthn server, passkey, xác thực'
category: 'Passkeys Implementation'
---

# So sánh 9 thư viện triển khai WebAuthn Server

## Key Facts

- **SimpleWebAuthn** (TypeScript, 1.000 sao trên GitHub) được đánh giá là trực quan nhất và là thư viện duy nhất cung cấp cả thư viện máy chủ lẫn thư viện trình duyệt frontend để triển khai passkey.
- Xác thực bằng passkey yêu cầu ít nhất **bốn endpoint API backend** so với một cho xác thực bằng mật khẩu, làm cho thư viện WebAuthn server trở nên thiết yếu để xử lý độ phức tạp của mật mã.
- **py_webauthn** (Python) là lý tưởng để thử nghiệm nhanh: các tùy chọn xác thực được tạo chỉ bằng một lệnh gọi phương thức và không yêu cầu cấu hình framework.
- **webauthn-framework** (PHP/Symfony, 347 sao) cung cấp tài liệu khái niệm phong phú nhất, làm cho nó trở nên tốt nhất cho các nhà phát triển học các nguyên tắc cơ bản về passkey từ đầu.
- Khi không có thư viện nào phù hợp với ngôn ngữ của bạn, **go-webauthn** hoặc SimpleWebAuthn là các lựa chọn dự phòng được đề xuất do sự áp dụng rộng rãi nhất trên các dự án thương mại và mã nguồn mở.

## 1. Giới thiệu: Triển khai WebAuthn Server

Cung cấp xác thực người dùng an toàn và đơn giản là yêu cầu bắt buộc đối với các công ty kỹ thuật số vào năm 2024. Passkey, với tư cách là tiêu chuẩn đăng nhập mới, là giải pháp lý tưởng để đáp ứng những nhu cầu này.
Tuy nhiên, trải nghiệm người dùng và bảo mật được nâng cao của passkey
đối với người dùng đi kèm với một cái giá khi triển khai chúng với tư cách là nhà phát triển. Độ khó triển khai
bắt nguồn từ thực tế là passkey tương đối mới - đối với người dùng, và cả
nhà phát triển và việc triển khai chúng có thể khá thách thức so với xác thực dựa trên mật khẩu. Trên thực tế, bạn cần ít nhất bốn endpoint API cho xác thực bằng passkey
so với một endpoint API cho xác thực bằng mật khẩu.

Một trong những thành phần cốt lõi ở phía máy chủ để cung cấp xác thực passkey là
**WebAuthn server (phần thư viện màu xanh lá cây).** Để có hướng dẫn toàn diện về cách WebAuthn
server phù hợp với tích hợp kiến trúc doanh nghiệp rộng lớn hơn, hãy xem bài viết chuyên dụng của chúng tôi.

![WebAuthn Server Architecture](https://www.corbado.com/website-assets/657d793ffb87095054194ebb_webauthn_server_architecture_e9ba5ad00c.png)_Nguồn:
[Yubico](https://developers.yubico.com/java-webauthn-server/)_

Trong bài đăng trên blog này, chúng tôi so sánh một số thư viện / package / SDK WebAuthn server, phân tích
sự khác biệt và đưa ra khuyến nghị cho các nhà phát triển mới làm quen với việc triển khai passkey.

## 2. Làm thế nào để tôi tự triển khai passkey?

Để hiểu rõ hơn tại sao lại cần **thư viện WebAuthn server** ngay từ đầu, hãy
xem xét cách thức passkey có thể được triển khai. Về nguyên tắc, có hai cách để
tích hợp passkey vào các trang web và ứng dụng:

1. Sử dụng giải pháp passkey của bên thứ ba (ví dụ: Corbado)
2. Tự triển khai passkey bằng cách sử dụng một trong các thư viện WebAuthn server dưới đây

Trong khi giải pháp passkey của bên thứ ba dễ dàng tích hợp và thường tiết kiệm rất nhiều
thời gian kỹ thuật (đặc biệt đối với các trường hợp ngoại lệ, bảo trì, khôi phục, dự phòng và cải thiện
trải nghiệm người dùng passkey), một số nhà phát triển chỉ thích tự triển khai mọi thứ.

Hãy cùng xem việc tự triển khai passkey hoạt động như thế nào. Trong một thiết lập
rất cơ bản, cần có một cơ chế để đăng ký (sign-up) và xác thực (đăng nhập). Cả hai
quy trình, còn được gọi là các nghi thức (ceremonies) WebAuthn, được xử lý khác nhau, mặc dù
luồng tổng thể tuân theo một sơ đồ tương tự:

1. **Frontend (trình duyệt) khởi tạo** một yêu cầu đăng ký hoặc đăng nhập và **gọi một endpoint API
   backend**.
2. **Backend tạo các tham số** đăng ký hoặc đăng nhập **WebAuthn**. Đây được gọi là
   PublicKeyCredentialCreationOptions và
   PublicKeyCredentialRequestOptions
   tương ứng. Một trong những phần quan trọng nhất của các tham số WebAuthn này là
   challenge. Các tham số WebAuthn sau đó được **gửi lại cho frontend**.
3. **Frontend** nhận các tham số WebAuthn này và sử dụng chúng để **xác minh
   danh tính của người dùng** bằng hệ thống xác thực thiết bị cục bộ (ví dụ: qua
   Face ID, Touch ID,
   Windows Hello). Trong quá trình đăng ký, một cặp
   khóa công khai-riêng tư mới được tạo, khóa riêng tư được lưu trữ cục bộ, trong khi khóa công khai
   được gửi đến máy chủ. Trong quá trình đăng nhập, **challenge được ký** bằng
   khóa riêng tư của passkey và gửi đến một endpoint API backend khác.
4. Trong quá trình đăng ký, backend **nhận khóa công khai** và lưu trữ nó. Khi đăng nhập,
   backend **nhận challenge đã ký và xác minh tính toàn vẹn của nó** bằng
   WebAuthn server.

Vì mọi quá trình đăng ký / đăng nhập đều bao gồm các bước này, backend cần theo dõi
người dùng, passkey và các yêu cầu đăng ký / đăng nhập.

Nếu bạn muốn có thêm kiến thức chuyên sâu về cách thức hoạt động của passkey và cách
thực hiện một triển khai đơn giản trông như thế nào (mà không sử dụng giải pháp passkey của bên thứ ba), bạn có thể
tìm hiểu bài viết trên blog của chúng tôi
[tại đây](http://ttps://www.corbado.com/blog/passkey-tutorial-how-to-implement-passkeys).

Trong các tình huống thực tế, khi tự triển khai passkey, hãy ghi nhớ rằng không chỉ là
việc cung cấp các endpoint API cần thiết và triển khai cơ bản để đăng ký và
đăng nhập. Ngoài ra, bạn cần giải quyết các chủ đề và trường hợp sử dụng sau:

- Quản lý thiết bị
- Các luồng đăng nhập đa nền tảng và đa thiết bị
- Quản lý người dùng
- Quản lý phiên bản (Session management)
- Phát hiện thiết bị sẵn sàng cho passkey
- Hướng dẫn người dùng
- Các tùy chọn xác thực dự phòng
- Các cơ chế khôi phục
- Các tùy chọn chia sẻ tài khoản
- Các luồng tạo passkey
  và luồng đăng nhập passkey được tối ưu hóa để có tỷ lệ chấp nhận cao

Tuy nhiên, đối với triển khai passkey cơ bản, bạn chỉ cần tuân thủ tiêu chuẩn
WebAuthn. Việc triển khai một thư viện WebAuthn server nổi tiếng và được hỗ trợ thường là
đủ. Thư viện tạo các tham số WebAuthn server và xác minh
các challenge đăng nhập, về cơ bản đảm nhận phần mật mã học và phức tạp nhất cho bạn.

## 3. Các thư viện Backend WebAuthn Server: Một sự so sánh

Tất cả các thư viện WebAuthn server được phân tích đều cung cấp các chức năng cần thiết để
cung cấp xác thực passkey. Do đó, chúng tôi đặc biệt chú ý đến các
tiêu chí sau:

- **Tiêu chí Lựa chọn Authenticator:** Làm thế nào bạn có thể thiết lập tùy chọn cho hành vi nhất định
  và các tính năng bảo mật (ví dụ: bắt buộc tạo resident keys)?
- **Cài đặt Toàn cầu (Global Settings):** Bạn có thể tập trung hóa cấu hình cần thiết đến mức nào?
- **Tài liệu:** Thư viện WebAuthn server được ghi chép tài liệu tốt như thế nào và có dễ theo dõi không
- **Ví dụ:** Có bất kỳ triển khai ví dụ nào mà bạn có thể lấy làm tham khảo không.

Các thư viện WebAuthn server sau đây đã được phân tích (sắp xếp theo số lượng sao
GitHub giảm dần vào tháng 12 năm 2023):

### 3.1 TypeScript: SimpleWebAuthn

![SimpleWebAuthn](https://www.corbado.com/website-assets/657d796db359dbc15ca87b17_webauthn_server_simplewebauthn_458503b246.png)

- **Ngôn ngữ Lập trình:** Typescript
- **Framework:** Node.js
- **Tác giả:** Matthew Miller (Duo Security / Cisco)
- **Số sao:** 1000
- **Được sử dụng bởi:** 781
- **Người đóng góp:** 19
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Không
- **Tiêu chí Lựa chọn Authenticator:** Như
  [W3C đề xuất](https://www.w3.org/TR/webauthn-2/#dictionary-authenticatorSelection)
  (nên chứa các biến authenticatorAttachment, residentKey, requireResidentKey và
  userVerification cũng được giải thích trên trang W3C)
- **Tài liệu:** Được cấu trúc tốt với trọng tâm là thiết lập nhanh và dễ sử dụng, bao gồm
  kiến thức về passkey, ví dụ: giải thích passkey là gì và cách chúng hoạt động
- **Ví dụ:** Dự án ví dụ có sẵn trong
  [tài liệu](https://simplewebauthn.dev/docs/advanced/example-project)
- **Cấu trúc dữ liệu được đề xuất:**

```json
type UserModel = {
  id: string;
  username: string;
  currentChallenge?: string;
};

/**
 * It is strongly advised that authenticators get their own DB
 * table, ideally with a foreign key to a specific UserModel.
 *
 * "SQL" tags below are suggestions for column data types and
 * how best to store data received during registration for use
 * in subsequent authentications.
 */
type Authenticator = {
  // SQL: Encode to base64url then store as `TEXT`. Index this column
  credentialID: Uint8Array;
  // SQL: Store raw bytes as `BYTEA`/`BLOB`/etc...
  credentialPublicKey: Uint8Array;
  // SQL: Consider `BIGINT` since some authenticators return atomic timestamps as counters
  counter: number;
  // SQL: `VARCHAR(32)` or similar, longest possible value is currently 12 characters
  // Ex: 'singleDevice' | 'multiDevice'
  credentialDeviceType: CredentialDeviceType;
  // SQL: `BOOL` or whatever similar type is supported
  credentialBackedUp: boolean;
  // SQL: `VARCHAR(255)` and store string array as a CSV string
  // Ex: ['usb' | 'ble' | 'nfc' | 'internal']
  transports?: AuthenticatorTransport[];
};
```

- **Các Đặc điểm Khác:**
  [WebAuthn Debugger cho các phản hồi WebAuthn](https://debugger.simplewebauthn.dev/) tuyệt vời và
  không chỉ cung cấp một thư viện backend / server mà còn cung cấp một thư viện cho frontend
  (về cơ bản đóng gói một số API Xác thực Web từ máy khách)
- **Đánh giá Cá nhân:** Thiết lập trực quan nhất được thấy cho đến nay và rất đơn giản.
  Hơn nữa, nó là một trong số ít các thư viện cũng cung cấp một thư viện trình duyệt để giúp với
  các triển khai máy khách khiến nó trở nên khá nổi bật. Tác giả của thư viện hoạt động rất tích cực
  trong cộng đồng WebAuthn / passkey.
- **Liên kết GitHub:**
  [https://github.com/MasterKale/SimpleWebAuthn](https://github.com/MasterKale/SimpleWebAuthn)

![SimpleWebAuthn Screenshot](https://www.corbado.com/website-assets/657d797be263ba3262fff816_webauthn_server_simplewebauthn_screenshot_527317d6be.png)

### 3.2 .NET: fido2-net-lib

![fido2-net-lib](https://www.corbado.com/website-assets/657d79968cef2987ff7c9c21_webauthn_server_fido2_net_lib_6727019f82.png)

- **Ngôn ngữ Lập trình:** C#
- **Framework:** .NET
- **Tác giả:** Anders Ã berg, Alex Seigler
- **Số sao:** 962
- **Được sử dụng bởi:** 200
- **Người đóng góp:** 40
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C
- **Tài liệu:** Chỉ là tệp Readme với một vài mẫu, một số
  [thông tin về passkey](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)
  trên [trang web](https://fido2-net-lib.passwordless.dev/) của thư viện
- **Ví dụ:** Bộ điều khiển Demo và kho lưu trữ thông tin xác thực ví dụ có sẵn để hiển thị tích hợp
  ví dụ
- **Cấu trúc dữ liệu được đề xuất:**

```json
public class StoredCredential
{
    /// <summary>
    /// The Credential ID of the public key credential source.
    /// </summary>
    public byte[] Id { get; set; }

    /// <summary>
    /// The credential public key of the public key credential source.
    /// </summary>
    public byte[] PublicKey { get; set; }

    /// <summary>
    /// The latest value of the signature counter in the authenticator data from any ceremony using the public key credential source.
    /// </summary>
    public uint SignCount { get; set; }

    /// <summary>
    /// The value returned from getTransports() when the public key credential source was registered.
    /// </summary>
    public AuthenticatorTransport[] Transports { get; set; }

    /// <summary>
    /// The value of the BE flag when the public key credential source was created.
    /// </summary>
    public bool IsBackupEligible { get; set; }

    /// <summary>
    /// The latest value of the BS flag in the authenticator data from any ceremony using the public key credential source.
    /// </summary>
    public bool IsBackedUp { get; set; }

    /// <summary>
    /// The value of the attestationObject attribute when the public key credential source was registered.
    /// Storing this enables the Relying Party to reference the credent’al's attestation statement at a later time.
    /// </summary>
    public byte[] AttestationObject { get; set; }

    /// <summary>
    /// The value of the clientDataJSON attribute when the public key credential source was registered.
    /// Storing this in combination with the above attestationObject item enables the Relying Party to re-verify the attestation signature at a later time.
    /// </summary>
    public byte[] AttestationClientDataJson { get; set; }

    public List<byte[]> DevicePublicKeys { get; set; }

    public byte[] UserId { get; set; }

    public PublicKeyCredentialDescriptor Descriptor { get; set; }

    public byte[] UserHandle { get; set; }

    public string AttestationFormat { get; set; }

    public DateTimeOffset RegDate { get; set; }

    public Guid AaGuid { get; set; }
}
```

- **Các Đặc điểm Khác:** Được sử dụng bởi
  Bitwarden (công ty khởi nghiệp
  passwordless.dev đã được mua lại bởi
  Bitwarden)
- **Đánh giá Cá nhân:** Thư viện thân thiện với nhà phát triển với một lượng tốt tài liệu bổ sung
- **Liên kết GitHub:**
  [https://github.com/passwordless-lib/fido2-net-lib](https://github.com/passwordless-lib/fido2-net-lib)

![fido2-net-lib Screentshot](https://www.corbado.com/website-assets/657d79aefc6fa186be1a722e_webauthn_server_fido2_net_lib_screenshot_a624ecd3d2.png)

### 3.3 Python: py_webauthn

![py_webauthn](https://www.corbado.com/website-assets/657d79c9b1ac103f4c903ec1_webauthn_server_py_webauthn_416b6eae90.jpg)

- **Ngôn ngữ Lập trình:** Python
- **Framework:** không cụ thể
- **Tác giả:** Duo Labs
- **Số sao:** 727
- **Được sử dụng bởi:** 912
- **Người đóng góp:** 23
- **Tuân thủ FIDO:** N/A
- **Cài đặt Toàn cầu:** Không
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C
- **Tài liệu:** Rất ít hoặc không có, yêu cầu kiến thức trước về passkey
- **Ví dụ:** Các mẫu mã nhỏ để đăng ký và đăng nhập được bao gồm
- **Cấu trúc dữ liệu được đề xuất:** N/A
- **Các Đặc điểm Khác:** Yêu cầu Python &gt;= 3.8
- **Đánh giá Cá nhân:** Thư viện tương đối nhỏ gọn với số lượng tệp nhỏ, bạn
  có thể có được cái nhìn tổng quan trong một khoảng thời gian ngắn.
- **Liên kết GitHub:**
  [https://github.com/duo-labs/py_webauthn](https://github.com/duo-labs/py_webauthn)

![py_webauthn Screenshot](https://www.corbado.com/website-assets/657d79da1eee1bef26c8ef4b_webauthn_server_py_webauthn_screenshot_5292be32e1.png)

### 3.4 Ruby: webauthn-ruby

![webauthn-ruby](https://www.corbado.com/website-assets/657d79ef3b5153896eb8fd4c_webauthn_server_webauthn_ruby_4fc3b288bd.png)

- **Ngôn ngữ Lập trình:** Ruby
- **Framework:** Ruby on Rails
- **Tác giả:** Cedarcode
- **Số sao:** 580
- **Được sử dụng bởi:** 679
- **Lượt tải Gem:** 18 Triệu
- **Người đóng góp:** 27
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C
- **Tài liệu:** Readme là nguồn tài liệu duy nhất
- **Ví dụ:** N/A
- **Cấu trúc dữ liệu được đề xuất:** N/A
- **Các Đặc điểm Khác:** Wrapper cho thư viện này cũng có sẵn
  ([warden-webauthn](https://github.com/ruby-passkeys/warden-webauthn),
  [devise-passkeys](https://github.com/ruby-passkeys/devise-passkeys))
- **Đánh giá Cá nhân:** Vì tài liệu bổ sung khá hạn chế nên chúng tôi chỉ
  đề xuất thư viện này nếu bạn quen thuộc với cả
  Ruby và Passkeys
- **Liên kết GitHub:**
  [https://github.com/cedarcode/webauthn-ruby](https://github.com/cedarcode/webauthn-ruby)

![webauthn-ruby Screenshot](https://www.corbado.com/website-assets/657d79fd54838aafd2274e4e_webauthn_server_webauthn_ruby_screenshot_7fb391a360.png)

### 3.5 Go: go-webauthn

![go-webauthn](https://www.corbado.com/website-assets/657d7a13b1ac103f4c908c60_webauthn_server_go_webauthn_f4f8db52ec.png)

- **Ngôn ngữ Lập trình:** Go
- **Framework:** Các framework dựa trên Go như Gin, Echo, ¦
- **Tác giả:** Ban đầu từ Duo Labs / được tiếp tục bởi James Elliott
- **Số sao:** 480
- **Được sử dụng bởi:** 280
- **Người đóng góp:** 18
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C
- **Tài liệu:** Readme với một số mẫu là nguồn tài liệu duy nhất
- **Ví dụ:** [Kho lưu trữ ví dụ ](https://github.com/ruby-passkeys/devise-passkeys)có sẵn
- **Cấu trúc Dữ liệu được Đề xuất:** N/A
- **Các Đặc điểm Khác:** Số lượng lớn tệp, việc có được cái nhìn tổng quan cần một chút thời gian
- **Đánh giá Cá nhân:** Thư viện phổ biến, dễ sử dụng khi bạn đã quen
  với nó, tuy nhiên chúng tôi khuyên bạn nên tìm hiểu một số kiến thức về passkey (Cách chúng hoạt động, quy trình
  trông như thế nào, v.v.) từ trước.
- **Liên kết GitHub:**
  [https://github.com/go-webauthn/webauthn](https://github.com/go-webauthn/webauthn)

![go-webauthn Screenshot](https://www.corbado.com/website-assets/657d7a266276ea8bd12bb480_webauthn_server_go_webauthn_screenshot_4bf908cdfd.png)

### 3.6 Java: java-webauthn-server

![java-webauthn-server](https://www.corbado.com/website-assets/657d7a49ac1b2446296c4e2b_webauthn_server_java_webauthn_server_368503276e.png)

- **Ngôn ngữ Lập trình:** Java
- **Framework:** Maven / Gradle
- **Tác giả:** Yubico
- **Số sao:** 391
- **Được sử dụng bởi:** N/A
- **Người đóng góp:** 27
- **Tuân thủ FIDO:** N/A
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C.
- **Tài liệu:** Readme là tài liệu duy nhất, nhưng khá chi tiết
- **Ví dụ:** N/A
- **Cấu trúc Dữ liệu được Đề xuất:** N/A
- **Các Đặc điểm Khác:** Đi kèm với giao diện Credential Repository, cung cấp hướng dẫn rõ ràng
  về các phương thức truy xuất cơ sở dữ liệu cần thiết.
- **Đánh giá Cá nhân:** Mặc dù bạn phải tự quản lý cơ sở dữ liệu, nhưng credential
  repository giúp ích đáng kể trong quá trình thiết kế cơ sở dữ liệu. Đương nhiên, các triển khai Java
  đi kèm với một số lượng lớn các tệp vì mỗi thuộc tính cần một lớp
  thường được lưu trữ trong tệp riêng của nó. Điều này làm cho việc xem xét tổng quan trở thành một
  nhiệm vụ tốn nhiều thời gian hơn.
- **Liên kết GitHub:**
  [https://github.com/Yubico/java-webauthn-server](https://github.com/Yubico/java-webauthn-server)

![java-webauthn-server Screenshot](https://www.corbado.com/website-assets/657d7a5aeac136d96d1bb459_webauthn_server_java_webauthn_server_screenshot_0cc89ca1ab.png)

### 3.7 Rust: webauthn-rs

![webauthn-rs](https://www.corbado.com/website-assets/657d7a6dd61bd50a76f5d9ca_webauthn_server_webauthn_rs_1be32ca83b.png)

- **Ngôn ngữ Lập trình:** Rust
- **Framework:** Dựa trên Rust (Rocket, Axum, ¦)
- **Tác giả:** Dự án Quản lý Danh tính Kanidm
- **Số sao:** 351
- **Được sử dụng bởi:** 617
- **Người đóng góp:** 25
- **Tuân thủ FIDO:** N/A
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Các khả năng cấu hình rất hạn chế. Các
  thư viện khác được triển khai chính xác theo Tiêu chuẩn W3C, hiển thị một
  khả năng cấu hình lớn hơn
- **Tài liệu:** Có tài liệu kỹ thuật được tạo tự động, nhưng không chi tiết lắm
- **Ví dụ:**
  [Kho lưu trữ hướng dẫn](https://github.com/kanidm/webauthn-rs/tree/master/tutorial) với
  ví dụ cho 3 framework web khác nhau có sẵn
- **Cấu trúc Dữ liệu được Đề xuất:** N/A
- **Các Đặc điểm Khác:** Thư viện đã vượt qua đợt kiểm tra bảo mật do bộ phận
  bảo mật sản phẩm SUSE thực hiện.
- **Đánh giá Cá nhân:** Vì khả năng cấu hình và tài liệu hạn chế, chúng tôi chỉ
  đề xuất thư viện này nếu framework chính của bạn dựa trên Rust và bạn biết cách passkey
  hoạt động
- **Liên kết GitHub:**
  [https://github.com/kanidm/webauthn-rs](https://github.com/kanidm/webauthn-rs)

![webauthn-rs Screenshot](https://www.corbado.com/website-assets/657d7a7db359dbc15ca91760_webauthn_server_webauthn_rs_screenshot_cc92cc955d.png)

### 3.8 PHP: webauthn-framework

![webauthn-framework](https://www.corbado.com/website-assets/657d7bd762d48bffd4a9b34d_webauthn_server_webauthn_framework_07cf99330e.png)

- **Ngôn ngữ Lập trình:** PHP
- **Framework:** Symfony
- **Tác giả:** Florent Morselli
- **Số sao:** 347
- **Được sử dụng bởi:** N/A
- **Người đóng góp:** 18
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Như đề xuất của W3C.
- **Tài liệu:** Tài liệu phong phú bao gồm các chi tiết kỹ thuật, nhưng cũng
  giải thích về passkey từ đầu
- **Ví dụ:** [Kho lưu trữ ví dụ](https://github.com/web-auth/symfony-webauthn-demo)
  có sẵn
- **Cấu trúc Dữ liệu được Đề xuất:**

```php
<?php

declare(strict_types=1);

namespace App\Entity;

use App\Repository\PublicKeyCredentialSourceRepository;
use DateTimeImmutable;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\AbstractUid;
use Symfony\Component\Uid\Uuid;
use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource;
use Webauthn\TrustPath\TrustPath;

#[ORM\Table(name: 'pk_credential_sources')]
#[ORM\Entity(repositoryClass: PublicKeyCredentialSourceRepository::class)]
class PublicKeyCredentialSource extends BasePublicKeyCredentialSource
{
    #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
    public readonly DateTimeImmutable $createdAt;

    #[ORM\Id]
    #[ORM\Column(type: Types::STRING, length: 255)]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private string $id;

    public function __construct(
        string $publicKeyCredentialId,
        string $type,
        array $transports,
        string $attestationType,
        TrustPath $trustPath,
        AbstractUid $aaguid,
        string $credentialPublicKey,
        string $userHandle,
        int $counter
    ) {
        $this->id = Uuid::v4()->toRfc4122();
        $this->createdAt = new DateTimeImmutable();
        parent::__construct($publicKeyCredentialId, $type, $transports, $attestationType, $trustPath, $aaguid, $credentialPublicKey, $userHandle, $counter);
    }

    public function getId(): string
    {
        return $this->id;
    }
}
```

- **Các Đặc điểm Khác:** N/A
- **Đánh giá Cá nhân:** Tốt cho những người muốn tìm hiểu về passkey nhưng không có
  kiến thức trước
- **Liên kết GitHub:**
  [https://github.com/web-auth/webauthn-framework](https://github.com/web-auth/webauthn-framework)

![webauthn-framework Screenshot](https://www.corbado.com/website-assets/657d7be96276ea8bd12cb5fd_webauthn_server_webauthn_framework_screenshot_9c1e9a3dd8.png)

### 3.9 Java: webauthn4j

![webauthn4j](https://www.corbado.com/website-assets/657d7c00fe6a1b80f0f03fd6_webauthn_server_webauthn4j_d8c4d2a9de.png)

- **Ngôn ngữ Lập trình:** Java
- **Framework:** Maven
- **Tác giả:** WebAuthn4j
- **Số sao:** 342
- **Được sử dụng bởi:** N/A
- **Người đóng góp:** 19
- **Tuân thủ FIDO:** Có
- **Cài đặt Toàn cầu:** Có
- **Tiêu chí Lựa chọn Authenticator:** Thay vì tham số UserVerificationRequirement
  được W3C đề xuất với các giá trị discouraged, preferred, required,
  webauthn4j cung cấp verificationRequired và userPrecenseRequired dưới dạng các biến Boolean
- **Tài liệu:** Tài liệu khô khan nhưng phong phú với một vài mẫu mã có sẵn
- **Ví dụ:** [Kho lưu trữ ví dụ](https://github.com/webauthn4j/webauthn4j-spring-security)
  có sẵn
- **Cấu trúc Dữ liệu được Đề xuất:** N/A
- **Các Đặc điểm Khác:** N/A
- **Đánh giá Cá nhân:** Đọc tài liệu nhanh chóng trở nên nhàm chán và phức tạp, vì
  nó chỉ là một trang lớn tập trung duy nhất vào chức năng chứ không phải khái niệm đằng sau
  passkey.
- **Liên kết GitHub:**
  [https://github.com/webauthn4j/webauthn4j](https://github.com/webauthn4j/webauthn4j)

![webauthn4j Screenshot](https://www.corbado.com/website-assets/657d7c7fb359dbc15caa2007_webauthn_server_webauthn4j_screenshot_3d7616a5e5.png)

Bảng sau đây cung cấp tổng quan về các thư viện WebAuthn server:

![WebAuthn Server Overview](https://www.corbado.com/website-assets/657d7c8fffd0b1429fd8d276_webauthn_server_implementation_overview_92a55c2e0f.png)

## 4. Các khuyến nghị: Điều hướng trong Bức tranh Thư viện WebAuthn

### 4.1 Bước 1: Chọn Thư viện WebAuthn của Bạn

Vì hầu hết các thư viện đều mạnh mẽ ngang nhau và triển khai tiêu chuẩn WebAuthn, chúng tôi
đề xuất cây quyết định sau:

- **Có Sẵn một Thư viện WebAuthn Server trong Framework & Ngôn ngữ Lập trình của Bạn:** Chúng tôi
  không liệt kê các thư viện framework phụ thuộc vào một trong các thư viện ở trên (ví dụ:
  có các tùy chỉnh cho PHP có sẵn cho Symfony và
  Laravel). Trong trường hợp có bản triển khai framework,
  hãy chọn bản này vì nó cho phép bạn triển khai các lệnh gọi API WebAuthn tự nhiên vào
  cấu trúc framework hiện tại của bạn và sử dụng lớp trừu tượng cơ sở dữ liệu của bạn để triển khai lưu trữ.
- **Có Sẵn một Thư viện WebAuthn Server trong Ngôn ngữ Lập trình của Bạn:** Vì bạn cần
  các endpoint API backend, hãy chọn thư viện WebAuthn server bằng ngôn ngữ lập trình bản địa của bạn
  để nó có thể được nhúng tự nhiên vào các endpoint API hiện tại của bạn.
- **Không có Thư viện WebAuthn Server nào Khả dụng trong Ngôn ngữ Lập trình của Bạn:** Trong
  trường hợp này, bạn nên cân nhắc sử dụng một giải pháp passkey được quản lý như Corbado. Nếu đó không phải
  là một tùy chọn, chúng tôi khuyên bạn nên sử dụng go-webauthn hoặc SimpleWebAuthn vì chúng có sự
  áp dụng lớn nhất, nhẹ và cũng được sử dụng bởi rất nhiều
  dự án thương mại và mã nguồn mở.

Nếu bạn chỉ muốn tìm hiểu thêm về WebAuthn server nói chung mà chưa có một
dự án cụ thể nào, chúng tôi có thể đưa ra một số khuyến nghị vì có một số khác biệt giữa
các thư viện và tài liệu bổ sung của chúng như tài liệu và các triển khai ví dụ. Vì vậy,
đối với các nhà phát triển phần mềm mong muốn khởi động hành trình triển khai passkey của họ, chúng tôi khuyên
bạn nên chọn các triển khai sau:

- **Để Thử nghiệm Nhanh:** Gói _py_webauthn_ cung cấp khả năng triển khai tức thì với
  các [đoạn mã](https://github.com/duo-labs/py_webauthn/blob/master/examples/registration.py)
  sẵn sàng sử dụng.
  Chỉ với một lệnh gọi phương thức, bạn có thể tạo các tùy chọn cần thiết cho việc xác thực.
  Vì bạn không cần nhúng thư viện vào framework và cấu hình nó, nó rất lý tưởng
  để thử nghiệm nhanh.
- **Để Triển khai Trực quan:** Gói _SimpleWebauthn_ được viết bằng Typescript
  rất đơn giản và thân thiện với nhà phát triển. Giống như _py_webauthn_, việc triển khai rất
  tối giản, nhưng nó đi kèm với tài liệu hướng dẫn bạn qua
  quá trình xác thực. Tuy nhiên, trái ngược với _py_webauthn_, _SimpleWebAuthn_ không
  đi kèm với một ví dụ rõ ràng chạy mà không cần sửa đổi.
- **Để Hiểu Sâu:** Thư viện _webauthn-framework_ cho PHP nổi bật với
  [tài liệu](http://Link) cấu trúc, phong phú tập trung vào các khái niệm passkey. Sự
  khác biệt chính so với các thư viện khác có lượng tài liệu tốt như _webauthn4j_ là thiết kế
  và sự sinh động của tài liệu.

Để hiểu sâu hơn nữa về cách WebAuthn hoạt động ở phía máy chủ, bạn có thể đọc
phần Hoạt động của WebAuthn Relying Party rất chi tiết trong
WebAuthn RFC, trong đó nêu chi tiết mọi bước cần được triển khai để
[đăng ký một thông tin xác thực mới (7.1)](https://www.w3.org/TR/webauthn-2/#sctn-registering-a-new-credential)
và
[xác minh assertion xác thực (7.2)](https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion).

### 4.2 Bước 2: Xác định Tùy chọn WebAuthn Server của Bạn

Đánh giá các yêu cầu passkey và WebAuthn cụ thể của bạn. Trong bài đăng trên blog này, chúng tôi
giả định bạn chỉ muốn hỗ trợ passkey dưới dạng thông tin xác thực có thể khám phá (discoverable credentials). Đọc về
PublicKeyCredentialCreationOptions và
PublicKeyCredentialRequestOptions cùng
với các lệnh gọi API WebAuthn phía máy khách navigator.credentials.create() và navigator.credentials.get()
để đặt các tham số trong cấu hình SDK WebAuthn server một cách chính xác cho
trường hợp sử dụng của bạn.

### 4.3 Bước 3: Xác định Cấu trúc Cơ sở Dữ liệu

Đối với tất cả các thư viện WebAuthn server, bạn sẽ cần cung cấp cấu trúc
cơ sở dữ liệu phù hợp để lưu trữ / truy cập thông tin sau:

- Thông tin xác thực (Credentials)
- Người dùng (Users)
- Challenges
- Authenticators

Đối với một số thư viện, có các đề xuất và ví dụ cụ thể (nếu chúng tôi thấy chúng
hữu ích, chúng tôi đã cung cấp chúng ở trên). Cần thiết phải hiểu đầy đủ trường WebAuthn
nào cần được lưu trữ ở đâu. Đặc biệt chú ý xác định giá trị nào bạn muốn
sử dụng cho User ID (user.id). Chúng tôi có một
giải thích chi tiết hơn tại đây. Ngoài ra, hãy xem xét điều gì sẽ xảy ra khi một người dùng có thể
xóa passkey. Bên cạnh đó, bạn có thể tùy chọn hạn chế việc sử dụng các authenticator nhất định. Danh sách các
authenticator hợp lệ liên quan đến passkey có thể được tìm thấy
[tại đây](https://github.com/passkeydeveloper/passkey-authenticator-aaguids). Trong trường hợp bạn
cũng muốn hỗ trợ và kiểm tra các attestation của khóa bảo mật (security keys),
đây là một câu chuyện hoàn toàn khác. Bạn có thể tìm thêm thông tin
[tại đây](https://fidoalliance.org/metadata/).

### 4.4 Bước 4: Kiểm tra Trên Thiết bị của Người Dùng

Xác định thiết bị nào người dùng của bạn sẽ sử dụng passkey và các phương pháp xác thực dự phòng. Trong trường hợp bạn không chắc chắn người dùng của mình sử dụng thiết bị, trình duyệt và hệ điều hành nào, hãy kiểm tra [State of Passkeys](https://state-of-passkeys.io/) để biết dữ liệu mới nhất về sự sẵn sàng cho passkey trên các nền tảng, trình duyệt và hệ điều hành. Nếu bạn có các câu hỏi cụ thể về việc áp dụng passkey và
tỷ lệ sẵn sàng cho passkey của một số thiết bị nhất định, vui lòng liên hệ với chúng tôi. Chúng tôi rất sẵn lòng cung cấp cho bạn những hiểu biết sâu sắc hơn và giúp đỡ bạn trong chủ đề này (xem thêm bài đăng trên blog mới nhất của chúng tôi về sự sẵn sàng của passkey). Theo góc nhìn về khả năng quan sát (observability), hãy giữ các lỗi WebAuthn phía máy khách và các từ chối xác minh của máy chủ dưới dạng các luồng riêng biệt; để định nghĩa bucket phía máy khách, hãy sử dụng các lỗi WebAuthn. Hơn nữa, bạn nên
nhớ rằng đối với Windows 10 và Linux, bạn sẽ cần đưa ra các
giải pháp chuyên dụng vì các hệ điều hành này cung cấp ít sự hỗ trợ cho passkey nhất (nếu có).

## 5. Kết luận

Đối với hầu hết mọi ngôn ngữ hoặc framework hiện nay đều có một thư viện WebAuthn server đã được thiết lập tốt. So sánh các thư viện của các ngôn ngữ khác nhau không cho thấy sự vượt trội rõ ràng
của một số triển khai nhất định. Thay vào đó, bạn nên sử dụng framework / ngôn ngữ lập trình mà bạn
quen thuộc nhất. Ngoài ra, nếu bạn không muốn tự triển khai WebAuthn và
lo liệu tất cả những thứ đi kèm, bạn có thể thử một giải pháp xác thực
passkey chuyên dụng, dựng sẵn như Corbado. Là một giải pháp xác thực tất cả trong một lấy passkey làm trung tâm, nó đi kèm với
[thông tin về passkey](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)
tuyệt vời, quản lý phiên bản cũng như các phương pháp xác thực dự phòng, vì vậy bạn có thể tập trung vào việc
phát triển sản phẩm của mình và bỏ qua vấn đề xác thực. Bạn có thể dùng thử miễn phí với
số lượng người dùng không giới hạn [tại đây](https://app.corbado.com/signin#register).

## Câu hỏi Thường gặp

### Làm cách nào để chọn thư viện WebAuthn server phù hợp cho dự án của tôi?

Đầu tiên hãy kiểm tra xem có thư viện nào cho framework cụ thể của bạn không, sau đó là cho ngôn ngữ lập trình của bạn. Vì tất cả các thư viện được liệt kê đều triển khai tiêu chuẩn WebAuthn như nhau, lựa chọn nên ưu tiên sự quen thuộc với stack công nghệ hiện tại của bạn thay vì sự khác biệt về tính năng giữa các thư viện.

### Tôi cần lưu trữ dữ liệu gì trong cơ sở dữ liệu khi xây dựng WebAuthn server?

Tối thiểu bạn phải lưu trữ thông tin xác thực, người dùng, challenge và authenticator. Hãy chú ý kỹ đến giá trị bạn gán làm User ID (userHandle) và lập kế hoạch cho các tình huống mà người dùng có thể xóa passkey khỏi thiết bị của họ.

### Tại sao tôi không thể tự triển khai xác minh WebAuthn phía máy chủ từ đầu mà không cần thư viện?

Các thư viện WebAuthn server xử lý các hoạt động mật mã phức tạp nhất: tạo tham số PublicKeyCredentialCreationOptions và PublicKeyCredentialRequestOptions cũng như xác minh các challenge đã được ký. Việc thực hiện đúng các thao tác này từ đầu khó hơn đáng kể so với việc sử dụng một thư viện tuân thủ FIDO đã được kiểm tra và đánh giá.

### Hệ điều hành nào có hỗ trợ passkey kém nhất và cần xử lý thêm trong triển khai WebAuthn?

Windows 10 và Linux cung cấp hỗ trợ passkey ít nhất, do đó cần có các giải pháp dự phòng chuyên dụng cho người dùng trên các nền tảng này. Việc giám sát các lỗi WebAuthn phía máy khách và máy chủ từ chối xác minh dưới dạng các luồng riêng biệt giúp xác định các vấn đề cụ thể của hệ điều hành trong môi trường production.
