PRD: Xác thực & xác minh tài khoản
| Module | Quản lý Người dùng (CORE-01) | PRD ID | PRD-AUTH-001 |
| Status | Shipped | Owner | Identity squad |
| Date | 2026-05-25 | Version | v1.0 |
| Packages | @nx/identity · apps/client | URD | AUTH |
TL;DR
Cho phép mọi người dùng chứng minh quyền sở hữu tài khoản và tự khôi phục quyền truy cập. Người dùng sign-up và sign-in bằng username, email hoặc điện thoại kèm mật khẩu, xác minh email và điện thoại bằng mã một lần (OTP), và đặt lại mật khẩu đã quên trọn vẹn - không cần mở ticket hỗ trợ. Kết quả: identifier mà các module khác có thể tin cậy, và một lối khôi phục tự phục vụ giúp chủ cửa hàng và nhân viên không bị khóa ngoài.
1. Bối cảnh & Vấn đề
Quản lý Người dùng là nền tảng của nền tảng - mọi module khác đều tin cậy danh tính và phạm vi mà nó cấp. Sign-up và sign-in bằng mật khẩu đã có, nhưng tài khoản chưa thể chứng minh quyền sở hữu một email hay điện thoại, và người dùng quên mật khẩu không có lối tự khôi phục. Khi chưa xác minh, một identifier email hay điện thoại chỉ là một chuỗi chưa được chứng thực; khi chưa có luồng reset, quên mật khẩu nghĩa là bị khóa cứng, chỉ có can thiệp thủ công mới gỡ được.
Đợt này lấp các khoảng trống đó trên nền các primitive sign-up / sign-in / băm mật khẩu sẵn có: bổ sung xác minh email và điện thoại bằng OTP, luồng đặt lại mật khẩu khi quên, liên kết identifier, và các màn hình client tiêu thụ chúng - đáp ứng các yêu cầu xác minh và khôi phục mà tính năng AUTH liệt kê là Must.
2. Mục tiêu & Không làm
Mục tiêu
- Sign-up tạo tài khoản, profile, identifier và default settings trong một thao tác duy nhất, tất cả hoặc không, role Owner được gán tự động.
- Sign-in bằng bất kỳ identifier đã xác minh (username / email / điện thoại) + mật khẩu, trả về một session token có phạm vi (role, phạm vi organizer, merchant).
- Đổi mật khẩu với mật khẩu hiện tại được xác minh trước; mật khẩu luôn lưu dạng băm.
- Xác minh email bằng OTP - yêu cầu mã → gửi mã → identifier được đánh dấu đã xác minh.
- Xác minh điện thoại bằng OTP theo cùng luồng yêu cầu/gửi mã.
- Đặt lại mật khẩu đã quên trọn vẹn - yêu cầu reset → xác minh mã → đặt mật khẩu băm mới.
- Liên kết một email hoặc điện thoại đã xác minh vào một tài khoản đã đăng nhập.
- Cấu hình mail và HTML template được seed từ database để mail xác minh / reset có thể cấu hình, không hardcode.
- Màn hình client cho việc xác minh identifier và đặt lại mật khẩu.
Không làm (Non-Goals)
- Luồng đăng nhập bên thứ ba OAuth / OAuth2 - scheme đã định nghĩa, luồng đăng nhập chưa xây (URD-AUTH-014).
- Bắt buộc xác thực hai yếu tố - credential scheme đã có, việc bắt buộc chưa xây (URD-AUTH-013).
- Quản lý phiên và thu hồi từ xa - session token là stateless.
- Mời người dùng qua email hoặc điện thoại.
- Ghi lịch sử / nhật ký đăng nhập (audit).
3. Success Metrics
| Chỉ số | Mục tiêu / tín hiệu |
|---|---|
| Hoàn tất xác minh | Tỷ lệ identifier email/điện thoại đạt trạng thái đã xác minh qua OTP tăng dần |
| Tự khôi phục | Số mật khẩu quên được giải quyết qua luồng reset, không cần hỗ trợ thủ công |
| Tính toàn vẹn sign-in | Không có ca sign-in thành công trên identifier chưa xác minh hoặc đã vô hiệu/bị chặn |
| An toàn credential | 100% mật khẩu lưu dạng băm; không lưu plain-text |
| Độ tin cậy OTP | Tỷ lệ gửi OTP thành công; lỗi hết hạn/quá số lần thử được xử lý mượt mà |
4. Personas & Use Case
| Persona | Mục tiêu trong tính năng này |
|---|---|
| Owner | Sign-up, bảo vệ tài khoản, xác minh email/điện thoại, khôi phục mật khẩu đã mất |
| Employee / Cashier | Sign-in bằng thông tin riêng, đổi hoặc đặt lại mật khẩu |
| Customer | Xác minh một identifier và khôi phục quyền truy cập tài khoản |
Kịch bản chính: sign-up (tài khoản + profile + identifier + settings, role Owner) → xác minh email/điện thoại bằng OTP → sign-in bằng identifier đã xác minh để nhận token có phạm vi → đổi mật khẩu, hoặc - nếu quên - yêu cầu reset, xác minh mã và đặt mật khẩu mới → tùy chọn liên kết thêm một email hoặc điện thoại đã xác minh.
5. User Stories
- Là một người dùng mới, tôi muốn sign-up bằng username và mật khẩu trong một bước, để tài khoản, profile, identifier và default settings được tạo cùng nhau.
- Là một người dùng, tôi muốn xác minh email bằng mã một lần, để nền tảng tin cậy identifier đó và tôi có thể sign-in bằng nó.
- Là một người dùng, tôi muốn xác minh điện thoại bằng cùng luồng OTP, để điện thoại trở thành một identifier dùng được, đáng tin.
- Là một người dùng, tôi muốn sign-in bằng bất kỳ identifier đã xác minh kèm mật khẩu, để nhận một session token mang role và phạm vi của mình.
- Là một người dùng, tôi muốn đổi mật khẩu sau khi xác nhận mật khẩu hiện tại, để xoay vòng credential an toàn.
- Là một người dùng quên mật khẩu, tôi muốn yêu cầu reset, xác minh mã và đặt mật khẩu mới, để khôi phục quyền truy cập mà không cần hỗ trợ.
- Là một người dùng đã đăng nhập, tôi muốn liên kết một email hoặc điện thoại đã xác minh vào tài khoản, để có thêm cách sign-in và khôi phục.
6. Functional Requirements
| # | Yêu cầu | URD ref |
|---|---|---|
| FR-1 | Sign-up bằng username + mật khẩu; tài khoản, profile, identifier và default settings tạo trong một thao tác duy nhất tất-cả-hoặc-không, gán role Owner | URD-AUTH-001..003 |
| FR-2 | Sign-in bằng bất kỳ identifier đã xác minh (username / email / điện thoại) + mật khẩu; trả session token mang role và phạm vi organizer / merchant | URD-AUTH-004..005 |
| FR-3 | Mật khẩu được băm an toàn trước khi lưu và không bao giờ lưu plain-text | URD-AUTH-006 |
| FR-4 | Đổi mật khẩu với mật khẩu hiện tại được xác minh trước | URD-AUTH-007 |
| FR-5 | Xác minh email bằng OTP: yêu cầu mã → gửi mã → identifier được đánh dấu đã xác minh | URD-AUTH-008 |
| FR-6 | Xác minh điện thoại bằng OTP theo cùng luồng yêu cầu/gửi mã | URD-AUTH-009 |
| FR-7 | Đặt lại mật khẩu đã quên: yêu cầu reset → xác minh mã → đặt mật khẩu băm mới | URD-AUTH-010 |
| FR-8 | Liên kết một email hoặc điện thoại đã xác minh vào tài khoản đã đăng nhập | URD-AUTH-011 |
| FR-9 | Identifier đã xác minh tham gia kiểm tra trùng lặp toàn cục (một email/điện thoại đã xác minh thuộc một người dùng) | URD-AUTH-008..009 |
| FR-10 | Cấu hình mail và HTML template được seed từ database, để mail xác minh / reset có thể cấu hình | URD-AUTH-008..010 |
Nội dung yêu cầu đầy đủ và tiêu chí chấp nhận nằm trong URD Quản lý Người dùng. PRD này tham chiếu, không lặp lại.
7. Non-Functional Requirements
| Khía cạnh | Yêu cầu |
|---|---|
| Toàn vẹn dữ liệu | Sign-up là một thao tác duy nhất - nếu bất kỳ bước nào thất bại, không tạo gì (tài khoản, profile, identifier, settings) |
| An toàn credential | Mật khẩu băm trước khi lưu; reset đặt mật khẩu băm; response reset không bao giờ mang session token |
| Tenancy & authz | Session token mang role và phạm vi organizer / merchant; mọi thao tác trừ sign-in / sign-up đều cần xác thực |
| Độ bền OTP | Mã OTP có thời hạn và giới hạn số lần thử; ca mã hết hạn và quá số lần trả lỗi rõ ràng |
| Stateless | Session token là stateless - thay đổi permission có hiệu lực ở lần sign-in kế tiếp |
| Khả năng cấu hình | Nội dung mail điều khiển bởi cấu hình và HTML template seed từ DB, không phải chuỗi hardcode |
| i18n | Nhãn, trạng thái và nội dung mail ở phần hiển thị là song ngữ ({ en, vi }) |
8. UX & Luồng
Màn hình chính (trong apps/client): một trang verify tiêu thụ endpoint yêu cầu/gửi OTP, và một trang quên-mật-khẩu / đặt-lại-mật-khẩu điều khiển luồng reset.
9. Dữ liệu & Domain
| Entity | Vai trò |
|---|---|
User | Danh tính đã xác thực, sở hữu credential, identifier, profile và settings |
Credential | Bí mật mật khẩu băm dùng để xác thực |
Identifier | Một giá trị đăng nhập (username / email / điện thoại), trùng lặp toàn cục theo từng loại, mang cờ verified |
| OTP session | Trạng thái ngắn hạn hỗ trợ xác minh và reset (yêu cầu → gửi, có thời hạn và giới hạn số lần) |
| Cấu hình mail + template | Cấu hình mail và HTML template seed từ DB cho mail xác minh / reset |
Chỉ mang tính khái niệm - schema đầy đủ và bất biến trong mô hình domain identity.
10. Phụ thuộc & Giả định
Phụ thuộc
- User Account (URD-USR) - người dùng, identifier và vòng đời
verifiedmà tính năng này điều khiển. - Roles & Scoping (URD-ROLE) - sign-up gán role Owner; sign-in phân giải role và phạm vi vào token.
- User Configuration (URD-CFG) - default settings tạo trong sign-up một-thao-tác-duy-nhất.
- Gửi mail cho mã OTP và mã reset;
apps/clientcho các màn hình verify và reset.
Giả định
- Một identifier (email/điện thoại) có thể nhận được để OTP được gửi tới.
- Cấu hình mail và template được seed trước khi gửi mail xác minh / reset.
- Username là bắt buộc và mặc định được coi là đã xác minh; email và điện thoại khởi đầu chưa xác minh.
11. Rủi ro & Câu hỏi mở
| Rủi ro / câu hỏi | Giảm thiểu / trạng thái |
|---|---|
| Sign-up dở dang có thể để lại mảnh tài khoản mồ côi | Sign-up là tất-cả-hoặc-không; bất kỳ thất bại nào cũng cuộn lại toàn bộ |
| Dò mã OTP / phát lại | Mã có thời hạn và giới hạn số lần thử; lỗi hết hạn/quá số lần rõ ràng |
| Response reset rò rỉ session token | Session token đã bị bỏ khỏi response đặt-lại-mật-khẩu |
| Xác minh email khi sign-up hiện đang tắt trong code | Khoảng trống đã biết - sign-up mới có thể cần một luồng verify riêng trước khi sign-in bằng email; xem developer docs |
| Chưa bắt buộc 2FA / chưa có đăng nhập OAuth | Ngoài phạm vi đợt này; credential scheme đã có, việc bắt buộc/luồng đăng nhập là planned |
12. Release Plan & Launch Criteria
| Khía cạnh | Kế hoạch |
|---|---|
| Phase | P1 (nền tảng) - xem danh mục tính năng URD |
| Rollout | Mọi người dùng; không feature flag |
| Migration | Seed cấu hình mail và HTML template; thêm các trường verified tùy chọn vào user schema |
| Launch criteria | Xác minh OTP email + điện thoại trọn vẹn; đặt-lại-mật-khẩu trọn vẹn; sign-in từ chối identifier chưa xác minh / đã vô hiệu; mật khẩu lưu dạng băm |
| Monitoring | Tỷ lệ gửi OTP + xác minh thành công, hoàn tất luồng reset, lý do sign-in thất bại (chưa xác minh / sai mật khẩu / bị chặn) |
13. FAQ
Tôi có thể sign-in bằng email hoặc điện thoại chưa xác minh không? Không - sign-in cần một identifier đã xác minh. Username được xác minh tự động; email và điện thoại phải qua OTP trước.
Luồng OTP hoạt động ra sao? Yêu cầu một mã cho email hoặc điện thoại (một session token được trả về), sau đó gửi mã; thành công thì identifier được đánh dấu đã xác minh. Mã có thời hạn và giới hạn số lần thử.
Nếu tôi quên mật khẩu thì sao? Yêu cầu reset, xác minh mã gửi qua email/tin nhắn, rồi đặt mật khẩu mới - nó được băm trước khi lưu, và response reset không bao giờ trả session token.
Mail xác minh và reset đến từ đâu? Cấu hình mail và HTML template được seed từ database, nên nội dung có thể cấu hình thay vì hardcode.
Có hỗ trợ OAuth hay xác thực hai yếu tố không? Không trong đợt này - cả hai scheme đã được định nghĩa nhưng luồng đăng nhập / việc bắt buộc là planned, chưa xây.
Tài liệu liên quan
- URD: Quản lý Người dùng - Authentication - yêu cầu + acceptance của AUTH
- Xây trên: User Account · Roles & Scoping · User Configuration
- PRD liên quan: Quản lý nhân viên · User Account & Configuration
- Module: Quản lý Người dùng - tổng quan + truy vết
- Developer: @nx/identity · mô hình domain