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 tạo dựa trên tiêu chuẩn mã hoá khoá công khai. Bằng cách tạo khoá truy cập, một cặp khoá riêng tư công khai 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 này đượ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 thông qua khoá công khai đã ghép nối. Cờ "có người dùng" (UP) trên thông tin xác thực khoá công khai chứng minh rằng ai đó đã 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 đúng người đã xuất hiện 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, điều này thường được thực hiện bằng cách sử dụng cơ chế khoá màn hình, cho dù đó là sinh trắc học, mã PIN hoặc mật khẩu. Việc quy trình xác minh người dùng có được báo cáo bằng cờ "UV" hay không đượ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 nhắc người dùng đăng nhập bằng Touch ID, hiển thị nguồn gốc yêu cầu xác thực cũng như tên người dùng. Ở phía trên bên phải của hộp thoại là nút có nhãn "Huỷ".
Hộp thoại xác minh người dùng trên Chuỗi khoá iCloud 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 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 nguồn gốc yêu cầu xác thực. Ở dưới cùng bên trái là lựa 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 có người dùng (UP) và cờ boolean được người dùng xác minh (UV) được báo hiệu đến máy chủ trong trường dữ liệu của trình xác thực. Trong quá trình xác thực, bạn có thể xác thực nội dung của trường dữ liệu trình 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ể xem là cờ thật.

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 có nội dung "RP ID HASH" (32 byte), "FLAGS" (1 byte), "bộ lọc" (4 byte, Big-endian uint32), "ATTESTE CRED". DATA' (độ dài thay đổi nếu có) và "EXTENSIONS" (độ dài thay đổi nếu có (CBOR)). Phần "FLAGS" đượ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 Authenticator trong thông tin xác thực khoá công khai.

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

Chỉ định tham số userVerification

Theo quy cách WebAuthn, bên bị hạn chế 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 thông tin xác thực và xác nhận. Phương thức này chấp nhận 'preferred', 'required' hoặc 'discouraged', lần lượt có nghĩa là:

  • 'preferred' (mặc định): Phương thức xác minh người dùng trên thiết bị được ưu tiên. Tuy nhiên, bạn có thể bỏ qua phương thức này nếu không có phương thức này. Thông tin đăng nhập phản hồi chứa giá trị cờ UV là true nếu xác minh người dùng và false nếu không thực hiện xác minh UV.
  • 'required': Bạn 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ó giá trị nào thì 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ề khi cờ UV được đặt thành true.
  • 'discouraged': Bạn 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ị, việc xác minh người dùng vẫn 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 phương á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 về ứng dụng, cũng như nhu cầu trải nghiệm người dùng của bạn.

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 khả năng bảo vệ.

Có những môi trường mà việc xác minh người dùng phức tạp hơn là bảo vệ. Ví dụ: trên macOS không có Touch ID (vì thiết bị không hỗ trợ, nó 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 của họ. Điều này gây phiền hà và người dùng có thể hoàn toàn bỏ qua bước xác thực. Nếu bạn quan tâm hơn đến việc loại bỏ phiền hà, 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 không có Touch ID. Hộp thoại này chứa các 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. Ở phía trên bên phải của hộp thoại là nút có nhãn "Huỷ".
Hộp thoại khoá truy cập hiển thị trên macOS khi không có Touch ID.

Với userVerification='preferred', cờ UV sẽ có giá trị true nếu quy trình xác minh người dùng được thực hiện thành công và false nếu quy trình xác minh người dùng bị bỏ qua. 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 bao gồm một cờ UV false.

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

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

Hãy dùng userVerification='required' nếu bạn cho rằng cả UP và UV đều thực sự 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 hà 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 quy trình xác minh người dùng, các bên dựa 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 hay đặt bước này là không bắt buộc, 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 sử dụng khoá truy cập.