Mật khẩu là một trong những thứ mà chúng ta đã bình thường hóa chỉ vì chúng ta đã sử dụng chúng trong nhiều năm. Người dùng quên chúng, sử dụng lại chúng, viết chúng vào những nơi không nên dùng. Các nhóm phải quản lý việc đặt lại, chính sách, băm, rò rỉ, lừa đảo và hỗ trợ.
passkey không giúp quá trình xác thực trở nên hoàn hảo nhưng chúng loại bỏ được một vấn đề lớn: máy chủ không còn phải giữ bí mật được chia sẻ với người dùng nữa.
Điều gì thực sự xảy ra
passkey là thông tin xác thực dựa trên WebAuthn. Khi người dùng tạo, thiết bị sẽ tạo ra một cặp khóa:
- khóa riêng vẫn còn trên thiết bị hoặc trong trình quản lý mật khẩu;
- một khóa công khai mà máy chủ có thể lưu.
Khi đăng nhập vào máy chủ không hỏi "cho tôi biết mật khẩu". Gửi một thử thách ngẫu nhiên. Thiết bị ký tên bằng khóa riêng. Máy chủ xác minh chữ ký bằng khóa chung.
Đó là phần hay: nếu cơ sở dữ liệu bị đánh cắp thì sẽ không có mật khẩu nào bên trong để bẻ khóa. Và nếu người dùng sử dụng một miền giả thì passkey sẽ không hợp lệ cho miền đó. Đó không chỉ là sự tiện lợi mà còn là sự bảo vệ cụ thể chống lại lừa đảo.
Trình duyệt đóng vai trò là cầu nối
Trong trình duyệt, hai API chính là:
navigator.credentials.create()để tạo passkey;navigator.credentials.get()để sử dụng nó trong quá trình đăng nhập.
Nhưng logic quan trọng là trên máy chủ. Máy chủ phải tạo thử thách, lưu tạm thời, xác minh phản hồi, kiểm tra nguồn và Relying Party ID, sau đó tạo phiên.
Phần client sẽ gần như nhàm chán:
const options = await fetch('/api/passkeys/login/options').then((r) => r.json()); const credential = await navigator.credentials.get({ publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options), }); await fetch('/api/passkeys/login/verify', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credential?.toJSON()), });
Nếu bạn thấy mình đang triển khai mã hóa WebAuthn bằng tay, hãy dừng lại. Sử dụng thư viện phía máy chủ mạnh mẽ. Lỗi ở đây không phải là "lỗi dễ thương" mà là lỗ hổng xác thực.
Lưu gì vào cơ sở dữ liệu
Không cần thiết phải cứu một nửa thế giới. Thông thường là đủ:
- ID của giấy chứng nhận;
- khóa công khai;
- người dùng được kết nối;
- bất kỳ bộ đếm xác minh hoặc siêu dữ liệu nào;
- phương tiện vận chuyển, nếu hữu ích cho UX;
- tên do người dùng chọn;
- ngày tạo và lần sử dụng cuối cùng.
Một bảng tối thiểu có thể trông như thế này:
create table passkey_credentials ( id uuid primary key default gen_random_uuid(), user_id uuid not null references users(id), credential_id text not null unique, public_key text not null, name text, created_at timestamptz not null default now(), last_used_at timestamptz );
Sau đó, tôi sẽ thêm nhật ký kiểm tra và thông báo: nếu ai đó tạo passkey mới trên tài khoản của tôi, tôi muốn biết về điều đó.
UX quan trọng hơn bản demo
Bản demo của passkey luôn đẹp: bạn nhấp vào, Face ID, bạn đã tham gia. Sản phẩm thực tế phức tạp hơn.
Có người thay đổi điện thoại của họ. Ai đó sử dụng máy tính công ty bị khóa. Một số người không hiểu tại sao trình duyệt lại gợi ý passkey. Ai đó mất quyền truy cập vào thiết bị của họ.
Đây là lý do tại sao tôi sẽ không bắt đầu với câu "từ hôm nay không còn mật khẩu nào cho mọi người nữa". Tôi sẽ bắt đầu như thế này:
- passkey tùy chọn đối với người dùng nội bộ;
- đề xuất tạo một tài khoản sau khi đăng nhập thành công;
- trang tài khoản để đổi tên và xóa passkey;
- dự phòng rõ ràng;
- triển khai dần dần trong lần đăng nhập chính.
Văn bản trong giao diện phải đơn giản. "Sử dụng màn hình khóa của thiết bị của bạn" tốt hơn là "xác thực bằng thông tin xác thực FIDO2 của cư dân."
Những sai lầm tôi sẽ tránh
Không tạo ra thách thức cho khách hàng. Thử thách được tạo trên máy chủ và chỉ phải được xác minh một lần.
Đừng chỉ tin tưởng vào ID thông tin xác thực. Bạn cần xác minh chữ ký, thách thức, nguồn gốc và Relying Party ID.
Đừng xóa các bản dự phòng trước khi bạn có quy trình khôi phục tốt. Không cần mật khẩu không nhất thiết phải trở thành "nếu bạn mất điện thoại, bạn sẽ bị loại vĩnh viễn".
Đừng coi passkey như một nút giao diện người dùng thuần túy. Ẩn nút không phải là bảo mật: xác minh thực sự là phía máy chủ.
Passkey-đầu tiên hay passkey-thân thiện?
Đối với một sản phẩm mới, bạn có thể nghĩ đến passkey-đầu tiên. Đối với ứng dụng hiện có, tôi thích passkey thân thiện hơn: thêm passkey làm phương pháp được đề xuất, đo lường mức độ thành công và vấn đề, sau đó bình tĩnh giảm trọng lượng mật khẩu.
Sự di cư lý tưởng không được cảm nhận. Người dùng phát hiện ra rằng việc đăng nhập dễ dàng hơn chứ không phải công ty đã thay đổi giao thức xác thực.
Kết luận
passkey rất thú vị vì chúng cải thiện tính bảo mật và trải nghiệm người dùng cùng một lúc, điều này rất hiếm. Chúng không phải là cây đũa thần: khả năng phục hồi, khả năng tương thích, hỗ trợ và triển khai vẫn phải được thiết kế tốt.
Nhưng sự thay đổi cơ bản là mạnh mẽ. Hãy ngừng yêu cầu người dùng phát minh và bảo vệ bí mật. Bạn để thiết bị ký bằng chứng mật mã gắn liền với miền của bạn. Ít bộ nhớ con người hơn, ít lừa đảo hơn, ít đặt lại mật khẩu hơn. Tôi muốn nói rằng chúng đáng được xem xét nghiêm túc.