Tìm hiểu chuyên sâu về userVerify

Tài liệu này thảo luận về userVerification trong WebAuthn và các hành vi của trình duyệt xảy ra khi userVerification được chỉ định trong quá trình tạo hoặc xác thực khoá truy cập.

"Xác minh người dùng" trong WebAuthn là gì?

Khoá truy cập được xây dựng dựa trên phương thức mã hoá khoá công khai. Khi bạn tạo khoá truy cập, một cặp khoá công khai-riêng tư sẽ được tạo, khoá riêng tư sẽ được trình cung cấp khoá truy cập lưu trữ và khoá công khai sẽ được trả về máy chủ của bên phụ thuộc (RP) để lưu trữ. Máy chủ có thể xác thực người dùng bằng cách xác minh chữ ký do cùng một khoá truy cập ký bằng khoá công khai đã ghép nối. Cờ "người dùng hiện diện" (UP) trên thông tin xác thực khoá công khai chứng minh rằng có người đã tương tác với thiết bị trong quá trình xác thực.

Xác minh người dùng là một lớp bảo mật không bắt buộc nhằm xác nhận rằng đã có đúng người trong quá trình xác thực, chứ không chỉ một người nào đó, như khẳng định sự hiện diện của người dùng. Trên điện thoại thông minh, việc này thường được thực hiện bằng cách sử dụng cơ chế khoá màn hình, có thể là dữ liệu sinh trắc học, mã PIN hoặc mật khẩu. Việc xác minh người dùng có được thực hiện hay không sẽ được báo cáo trong cờ "UV" được trả về trong dữ liệu trình xác thực trong quá trình đăng ký và xác thực khoá truy cập

Ảnh chụp màn hình hộp thoại xác minh người dùng trên iCloud Keychain trên macOS. Hộp thoại này nhắc người dùng đăng nhập bằng Touch ID, hiển thị nguồn yêu cầu xác thực cũng như tên người dùng. Ở trên cùng bên phải của hộp thoại là một nút có nhãn "Cancel" (Huỷ).
Hộp thoại xác minh người dùng trên iCloud Keychain trên macOS.
Ảnh chụp màn hình hộp thoại xác minh người dùng trên Chrome dành cho Android. Hộp thoại này nhắc người dùng xác minh danh tính bằng cách sử dụng tính năng nhận dạng khuôn mặt hoặc phát hiện vân tay, đồng thời hiển thị nguồn gốc yêu cầu xác thực. Ở dưới cùng bên trái là tuỳ chọn xác minh bằng mã PIN.
Hộp thoại xác minh người dùng trên Android Chrome.

Cách xác thực UP và UV trên máy chủ

Cờ boolean về sự hiện diện của người dùng (UP) và người dùng đã xác minh (UV) được báo hiệu cho máy chủ trong trường dữ liệu trình xác thực. Trong quá trình xác thực, nội dung của trường dữ liệu trình xác thực có thể được xác thực bằng cách xác minh chữ ký bằng khoá công khai đã lưu trữ. Miễn là chữ ký hợp lệ, máy chủ có thể coi các cờ là hợp lệ.

Hình ảnh mô tả cấu trúc dữ liệu xác thực. Từ trái sang phải, mỗi phần của cấu trúc dữ liệu sẽ đọc là "RP ID HASH" (32 byte), "FLAGS" (1 byte), "COUNTER" (4 byte, big-endian uint32), "ATTESTE CRED. DATA' (độ dài biến nếu có) và 'EXTENSIONS' (độ dài biến nếu có (CBOR)). Phần "CỜ" được mở rộng để hiển thị danh sách các cờ tiềm năng, được gắn nhãn từ trái sang phải: "ED", "AT", "0", "BS", "BE", "UV", "0" và "UP".
Các trường dữ liệu của trình xác thực trong thông tin xác thực bằng khoá công khai.

Khi đăng ký và xác thực khoá truy cập, máy chủ phải kiểm tra để đảm bảo cờ UP là true và cờ UV là true hay false, tuỳ thuộc vào yêu cầu.

Chỉ định tham số userVerification

Theo quy cách WebAuthn, RP có thể yêu cầu xác minh người dùng bằng tham số userVerification trong cả quá trình tạo và xác nhận thông tin xác thực. Phương thức này chấp nhận 'preferred', 'required' hoặc 'discouraged', tương ứng với các nghĩa sau:

  • 'preferred' (mặc định): Việc sử dụng phương thức xác minh người dùng trên thiết bị được ưu tiên nhưng bạn có thể bỏ qua nếu không có phương thức này. Thông tin xác thực phản hồi chứa giá trị cờ UV là true nếu đã thực hiện quy trình xác minh người dùng và false nếu không thực hiện quy trình UV.
  • 'required': Bắt buộc phải gọi một phương thức xác minh người dùng có trên thiết bị. Nếu không có, yêu cầu sẽ không thành công trên máy. Điều này có nghĩa là thông tin xác thực phản hồi luôn trả về với cờ UV được đặt thành true.
  • 'discouraged': Không nên sử dụng phương thức xác minh người dùng. Tuy nhiên, tuỳ thuộc vào thiết bị, quá trình xác minh người dùng có thể được thực hiện và cờ UV có thể chứa true hoặc false.

Mã mẫu để tạo khoá truy cập:

const publicKeyCredentialCreationOptions = {
  // ...
  authenticatorSelection: {
    authenticatorAttachment: 'platform',
    residentKey: 'required',
    requireResidentKey: true,
    userVerification: 'preferred'
  }
};

const credential = await navigator.credentials.create({
  publicKey: publicKeyCredentialCreationOptions
});

Mã mẫu để xác thực khoá truy cập:

const publicKeyCredentialRequestOptions = {
  challenge: /* Omitted challenge data... */,
  rpId: 'example.com',
  userVerification: 'preferred'
};

const credential = await navigator.credentials.get({
  publicKey: publicKeyCredentialRequestOptions
});

Bạn nên chọn tuỳ chọn nào cho userVerification?

Giá trị userVerification mà bạn nên sử dụng phụ thuộc vào các yêu cầu của ứng dụng cũng như nhu cầu về trải nghiệm người dùng.

Trường hợp sử dụng userVerification='preferred'

Sử dụng userVerification='preferred' nếu bạn ưu tiên trải nghiệm người dùng hơn là khả năng bảo vệ.

Có những môi trường mà việc xác minh người dùng gây ra nhiều phiền toái hơn là bảo vệ. Ví dụ: trên macOS không có Touch ID (vì thiết bị không hỗ trợ, bị tắt hoặc thiết bị đang ở chế độ vỏ sò), người dùng sẽ được yêu cầu nhập mật khẩu hệ thống. Điều này gây ra sự phiền hà và người dùng có thể hoàn toàn bỏ qua quy trình xác thực. Nếu việc loại bỏ sự cố trượt quan trọng hơn đối với bạn, hãy sử dụng userVerification='preferred'.

Ảnh chụp màn hình hộp thoại khoá truy cập trên macOS, xuất hiện khi Touch ID không có sẵn. Hộp thoại này chứa thông tin như nguồn gốc yêu cầu xác thực cũng như tên người dùng. Ở trên cùng bên phải của hộp thoại là một nút có nhãn "Cancel" (Huỷ).
Hộp thoại khoá truy cập xuất hiện trên macOS khi không có Touch ID.

Với userVerification='preferred', cờ UV là true nếu xác minh người dùng thành công và false nếu bỏ qua quy trình xác minh người dùng. Ví dụ: trên macOS không có Touch ID, hệ thống sẽ yêu cầu người dùng nhấp vào một nút để bỏ qua quy trình xác minh người dùng và thông tin xác thực khoá công khai có cờ UV false.

Sau đó, cờ UV có thể là một tín hiệu trong quá trình phân tích rủi ro. Nếu lượt đăng nhập có vẻ rủi ro do các yếu tố khác, bạn nên đưa ra các thử thách đăng nhập bổ sung cho người dùng nếu chưa xác minh người dùng.

Trường hợp sử dụng userVerification='required'

Sử dụng userVerification='required' nếu bạn cho rằng cả UP và UV đều cần thiết.

Nhược điểm của lựa chọn này là người dùng có thể gặp nhiều phiền toái hơn khi đăng nhập. Ví dụ: trên macOS không có Touch ID, người dùng sẽ được yêu cầu nhập mật khẩu hệ thống.

Với userVerification='required', bạn có thể đảm bảo việc xác minh người dùng được thực hiện trên thiết bị. Đảm bảo máy chủ xác minh rằng cờ UV là true.

Kết luận

Bằng cách tận dụng tính năng xác minh người dùng, các bên phụ thuộc vào khoá truy cập có thể đánh giá khả năng chủ sở hữu thiết bị đăng nhập. Họ có thể chọn yêu cầu xác minh người dùng hoặc không yêu cầu, tuỳ thuộc vào mức độ quan trọng của cơ chế đăng nhập dự phòng đối với luồng người dùng. Đảm bảo máy chủ kiểm tra cờ UP và cờ UV để xác thực người dùng bằng khoá truy cập.