[DDD] Thiết kế Chi tiết Tính năng Đăng nhập
Tài liệu này trình bày thiết kế kỹ thuật chi tiết cho luồng xác thực người dùng (Đăng nhập). Nó bao gồm thiết kế giao diện, luồng xác thực, định dạng API, cấu trúc CSDL và các biện pháp bảo mật quan trọng.
1. Tổng quan (Overview)
1.1. Bối cảnh và Vấn đề
Hệ thống cần một cơ chế an toàn để xác định danh tính người dùng, cho phép họ truy cập vào các tài nguyên và tính năng được cá nhân hóa. Nếu không có tính năng đăng nhập, chúng ta không thể cung cấp trải nghiệm riêng tư và bảo vệ dữ liệu người dùng.
1.2. Mục tiêu & Phi mục tiêu (Goals and Non-Goals)
Mục tiêu (Goals)
- Cung cấp một giao diện đăng nhập an toàn và thân thiện.
- Xác thực người dùng dựa trên Số điện thoại và mật khẩu.
- Trả về một token (JWT) để client sử dụng cho các yêu cầu tiếp theo.
- Thời gian phản hồi cho một lần đăng nhập thành công phải dưới 500ms (P95).
Phi mục tiêu (Non-Goals)
- Đăng nhập bằng tài khoản mạng xã hội (Google, Facebook).
- Xác thực hai yếu tố (2FA).
Các "phi mục tiêu" sẽ được thiết kế trong các tài liệu riêng biệt để giữ cho phạm vi của tài liệu này được tập trung.
2. Kiến trúc Tổng thể (Overall Architecture)
Luồng đăng nhập sẽ đi qua các thành phần chính sau:
3. Thiết kế Chi tiết (Detailed Design)
3.1. Thiết kế Giao diện & Luồng người dùng (UI & User Flow)
- Các thành phần giao diện:
Ô nhập Số điện thoại,Ô nhập Mật khẩu,Nút "Đăng nhập",Thông báo lỗi (hiển thị khi đăng nhập thất bại). - Luồng người dùng:
- Người dùng truy cập trang
/login. - Giao diện hiển thị hai ô để người dùng nhập: Số điện thoại và Mật khẩu
- Người dùng nhập thông tin và nhấn "Đăng nhập"
- Trong lúc hệ thống kiểm tra thông tin, nút sẽ bị khóa và hiển thị trạng thái đang xử lý.
- Trường hợp thành công:
- Hệ thống ghi nhận thông tin người dùng và quyền truy cập.
- Sau đó, người dùng được chuyển sang trang chính của hệ thống.
- Trường hợp thất bại:
- Nút "Đăng nhập" sẽ được bật lại để người dùng thử lại.
- Một thông báo lỗi sẽ hiển thị, ví dụ: “Số điện thoại hoặc mật khẩu không chính xác.”
- Người dùng truy cập trang
3.2. Luồng Tương tác (Interaction Flow)
3.2. Thiết kế API (API Design)
Endpoint: POST /api/v1/auth/login
Request Body:
{
"phone_number": "0933xxxxx",
"password": "user_password_123"
}
Response (Success - 200 OK):
{
{
"success": true,
"message": "Login successful",
"data": {
"AccessToken": "eyJr...",
"ExpiresIn": 86400,
"TokenType": "Bearer",
"RefreshToken": "eyJj..",
"IdToken": "eyJr...",
"SessionId": "8bc21...",
"UserInfo": {
"username": "longngo",
"email": "vip@gmail.com",
"email_verified": false,
"phone_number": "+84909xxxxxx",
"phone_number_verified": false,
"name": "Broker",
"family_name": "Broker",
"given_name": "Broker",
"picture": "...",
"role": "broker",
"sub": "..."
}
}
}
}
Response (Error):
- 400 Bad Request: Nếu Số điện thoại không hợp lệ hoặc thiếu trường.
{"success":false,"message":"Field phone_number value is invalid","error_code":"auth.error.validation_error"} - 401 Unauthorized: Nếu Số điện thoại hoặc mật khẩu không chính xác.
{
"success": false,
"message": "Phone number or password is incorrect",
"error_code": "auth.error.NotAuthorizedException.user_password_login"} - 429 Too Many Requests: Nếu người dùng cố gắng đăng nhập quá nhiều lần.
TUYỆT ĐỐI KHÔNG lưu mật khẩu dưới dạng văn bản thuần (plain text). Luôn sử dụng các thuật toán hashing mạnh, có salt như Bcrypt hoặc Argon2.
4. Các yếu tố phi chức năng (Non-Functional Requirements)
4.1. Bảo mật (Security)
- HTTPS/TLS: Tất cả các giao tiếp phải được mã hóa qua HTTPS.
- Password Hashing: Sử dụng Bcrypt với cost factor >= 10.
- Rate Limiting: Giới hạn số lần đăng nhập thất bại từ một địa chỉ IP (ví dụ: 5 lần trong 5 phút) để chống lại tấn công Brute Force.
- Credential Stuffing Protection: Sử dụng các dịch vụ như Have I Been Pwned? để kiểm tra mật khẩu bị rò rỉ hoặc yêu cầu CAPTCHA sau nhiều lần thất bại.
- JWT Security:
accessTokencó thời gian sống ngắn (15-30 phút).refreshTokencó thời gian sống dài (7-30 ngày), được lưu trữ an toàn (HttpOnly cookie) và có thể bị thu hồi.- Sử dụng thuật toán ký mạnh (ví dụ:
RS256thay vìHS256).
4.2. Hiệu năng & Khả năng mở rộng (Performance & Scalability)
- Service
Authphải là stateless để có thể dễ dàng scale theo chiều ngang. Trạng thái (session) được quản lý bởi JWT ở phía client. - Đảm bảo có index trên cột
Số điện thoạicủa bảngusersđể truy vấn nhanh.
5. Các phương án đã cân nhắc (Alternatives Considered)
| Phương án | Ưu điểm | Nhược điểm | Lý do chọn JWT |
|---|---|---|---|
| JWT-based Authentication (Đã chọn) | Stateless, dễ scale, thân thiện với mobile/SPA. | Token có thể lớn, khó thu hồi ngay lập tức nếu không có blacklist. | Phù hợp với kiến trúc microservices và các client đa dạng. |
| Server-side Sessions (Session-Cookie) | Dễ thu hồi (chỉ cần xóa session trên server). | Stateful (khó scale), không thân thiện với non-web clients. | Không phù hợp với kiến trúc stateless của chúng ta. |
6. Rủi ro và Phương án giảm thiểu (Risks and Mitigation)
| Rủi ro | Mức độ ảnh hưởng | Khả năng xảy ra | Phương án giảm thiểu |
|---|---|---|---|
| Tấn công Brute Force / Credential Stuffing | Cao | Trung bình | Implement Rate Limiting, CAPTCHA, giám sát các lần đăng nhập thất bại. |
Rò rỉ accessToken (XSS Attack) | Cao | Trung bình | Thời gian sống ngắn, lưu trong bộ nhớ thay vì localStorage. |
Rò rỉ refreshToken | Rất cao | Thấp | Lưu trong HttpOnly, SameSite cookie. Implement cơ chế thu hồi. |
| Rò rỉ CSDL chứa mật khẩu | Rất cao | Thấp | Sử dụng Hashing mạnh (Bcrypt/Argon2). |
Tài liệu tham khảo: