> ## Documentation Index
> Fetch the complete documentation index at: https://tomotek.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# US-OWN-02: Đăng ký và Đăng nhập

> Là một Chủ nuôi (Pet Owner), Tôi muốn đăng ký hoặc đăng nhập vào ứng dụng bằng tài khoản Google/SĐT/Email/Apple, Để tôi có thể truy cập hệ thống một cách nhanh chóng, bảo mật

## Điều kiện tiên quyết (Pre-conditions)

Để User Story này có thể thực hiện và nghiệm thu, hệ thống cần đáp ứng các điều kiện sau:

* **Better Auth:** Đã cài đặt và cấu hình thư viện Better Auth trên Backend (Node.js).
* **Google Cloud Console:** Đã tạo Project, cấu hình OAuth 2.0 Client ID và Secret, đồng thời khai báo các Redirect URIs hợp lệ.
* **Apple Developer:** Đã cấu hình Sign in with Apple, thiết lập Services ID và xác nhận domain.
* **OTP Provider:** Đã tích hợp thành công dịch vụ gửi thông qua Email, SMS để gửi mã xác thực.
* **Cơ sở dữ liệu:** Các bảng lưu trữ User, Session, Account (theo chuẩn Better Auth) đã được định nghĩa.
* **Phone Number Normalization:** Hệ thống hỗ trợ chuẩn hóa định dạng số điện thoại quốc tế (E.164).

## Quy trình Đăng ký tài khoản (Bắt buộc OTP)

Để đảm bảo định danh liên lạc là chính xác khi tạo tài khoản:

> [tab]  Đăng ký với Email
>
> ```mermaid theme={null}
> flowchart TB
> A["Nhập Email + Mật khẩu + Xác nhận mật khẩu"] --> B{"Kiểm tra Email tồn tại?"}
>
> B -- "Đã có tài khoản" --> C["Thông báo: Email đã tồn tại, chuyển sang Đăng nhập"]
>
> B -- "Chưa tồn tại" --> D{"Đã tích đồng ý điều khoản?"}
>
> D -- "Chưa đồng ý" --> E["Nút Đăng ký bị vô hiệu hóa"]
>
> D -- "Đã đồng ý" --> F["Gửi OTP 6 chữ số vào Email"]
>
> F --> G["Người dùng nhập mã OTP"]
>
> G --> H{"OTP hợp lệ? (5 phút)"}
>
> H -- "Sai / Hết hạn" --> I["Thông báo lỗi, cho phép nhập lại"]
>
> H -- "Đúng" --> J["Tạo bản ghi User mới"]
>
> J --> K["Quay trở lại màn đăng nhập"]
> ```

> [tab]  Đăng ký với Số Điện Thoại
>
> ```mermaid theme={null}
> flowchart TB
> A["Nhập Số điện thoại + Mật khẩu + Xác nhận mật khẩu"] --> B{"Số điện thoại tồn tại?"}
>
> B -- "Đã có tài khoản" --> C["Thông báo: SĐT đã tồn tại, chuyển sang Đăng nhập"]
>
> B -- "Chưa tồn tại" --> D{"Đã tích chọn đồng ý điều khoản?"}
>
> D -- "Chưa đồng ý" --> E["Nút Tiếp tục bị vô hiệu hóa"]
>
> D -- "Đã đồng ý" --> F["Hệ thống gửi OTP 6 chữ số qua SMS"]
>
> F --> G["Người dùng nhập mã OTP"]
>
> G --> H{"Xác thực OTP hợp lệ? (5 phút)"}
>
> H -- "Sai / Hết hạn" --> I["Thông báo lỗi, cho phép nhập lại"]
>
> H -- "Đúng" --> J["Tạo bản ghi User mới"]
>
> J --> K["Quay trở lại màn đăng nhập "]
>
> ```

> [tab]  Đăng ký nhanh với Google/Apple
>
> 1. Người dùng nhấn nút **Tiếp tục với Google** / **Tiếp tục với Apple**
> 2. Hiện Popup xác thực bên thứ 3
> 3. Xác thực thành công → Kiểm tra tài khoản đã tồn tại chưa
> 4. Chưa có tài khoản → Tạo User mới tự động
> 5. Vào thẳng ứng dụng ngay lập tức (Không cần OTP, không cần đặt mật khẩu)

| Trường thông tin | Bắt buộc | Validate & Ràng buộc |
| - | - | - |
| **Email** | Tùy chọn | Định dạng Email hợp lệ, kiểm tra tồn tại |
| **Số điện thoại** | Tùy chọn | Định dạng VN hợp lệ, kiểm tra tồn tại, không cho phép số ảo |
| **Mật khẩu** | Bắt buộc (khi đăng ký Email/SĐT) | Tối thiểu 8 ký tự |
| **Xác nhận mật khẩu** | Bắt buộc (khi đăng ký Email/SĐT) | Phải trùng khớp với mật khẩu |
| **Đồng ý Điều khoản & Chính sách** | Bắt buộc | Phải tích chọn checkbox |

> Người dùng có thể chọn đăng ký bằng **Email** HOẶC **Số điện thoại**, không cần cung cấp cả hai.

## Quy trình Đăng nhập (Không cần OTP)

Sau khi đã có tài khoản, việc truy cập phải diễn ra nhanh chóng:

> [tab]  Đăng nhập với Google
>
> 1. Người dùng nhấn nút **Tiếp tục với Google**
> 2. Hiện Popup xác thực Google
> 3. Xác thực thành công → Vào thẳng ứng dụng ngay lập tức (Không cần OTP)

> [tab]  Đăng nhập với Apple
>
> 1. Người dùng nhấn nút **Tiếp tục với Apple**
> 2. Xác thực với Face ID / Touch ID / Mật khẩu Apple ID
> 3. Xác thực thành công → Vào thẳng ứng dụng ngay lập tức (Không cần OTP)

> [tab] Đăng nhập với Email/SĐT & Mật khẩu
>
> 1. Người dùng nhập Email/SĐT và Mật khẩu đã thiết lập lúc đăng ký
> 2. Kiểm tra thông tin hợp lệ → Vào hệ thống ngay lập tức (Không cần OTP)

**Phiên đăng nhập luôn tồn tại cho đến khi người dùng thực hiện thủ công log out**

## Quên mật khẩu

```mermaid theme={null}
flowchart TB
    A[Nhấn Quên mật khẩu] --> B[Chọn phương thức khôi phục: Email / Số Điện Thoại]
    B --> C[Nhập Email hoặc Số điện thoại tài khoản]
    C --> D{Kiểm tra thông tin tồn tại?}
    D -->|Không tồn tại| E[Thông báo không tìm thấy tài khoản]
    D -->|Tồn tại| F[Gửi OTP 6 chữ số qua Email/SMS tương ứng]
    F --> G[Nhập OTP nhận được]
    G --> H{Xác thực OTP hợp lệ?}
    H -->|Sai / Hết hạn| I[Thông báo lỗi, cho phép gửi lại OTP]
    H -->|Đúng| J[Nhập mật khẩu mới + Xác nhận]
    J --> K[Cập nhật mật khẩu mới]
    K --> L[Chuyển đến màn hình Đăng nhập]
```

* OTP quên mật khẩu có hiệu lực **3 phút**
* Giới hạn gửi OTP: 1 lần / 1 phút
* Sau 5 lần nhập OTP sai: khóa tính năng trong 10 phút
* Mật khẩu mới không được trùng với 3 mật khẩu gần nhất
* Sau khi đổi mật khẩu thành công: tất cả phiên đăng nhập cũ bị đăng xuất tự động
* Hỗ trợ khôi phục qua cả Email và Số điện thoại đã đăng ký

## Ràng buộc Bảo mật & Xử lý lỗi

| Quy tắc | Mô tả |
| - | - |
| Kiểm tra tồn tại | Nếu người dùng dùng tính năng "Đăng ký" cho một Email/SĐT đã có tài khoản, hệ thống thông báo rõ ràng và gợi ý chuyển sang màn hình Đăng nhập |
| Rate Limit | Giới hạn gửi OTP đăng ký (Tối đa 1 lần/1 phút) để tránh bị spam mail/SMS server |
| Password Hashing | Mật khẩu phải được mã hóa (Bcrypt) trước khi lưu vào DB (Better Auth tự động xử lý phần này) |
| Session Persistence | Phiên đăng nhập được duy trì vĩnh viễn đến khi người dùng chủ động đăng xuất |
| Google OAuth | Không yêu cầu OTP hay bước bổ sung nào sau khi xác thực Google thành công |
| Sign in with Apple | Hỗ trợ chế độ ẩn Email, hệ thống tự động xử lý email proxy do Apple cung cấp |

## Giao diện đề xuất

> [accordion] Màn hình Đăng ký
>
> * Tab chuyển đổi giữa Đăng ký Email và Đăng ký Số điện thoại
> * Input Email/Số điện thoại với validation realtime
> * Input Mật khẩu + Xác nhận mật khẩu
> * Checkbox đồng ý Điều khoản sử dụng và Chính sách bảo mật (bắt buộc)
> * Link mở Modal/WebView xem nội dung Điều khoản
> * Nút Đăng ký (bật/tắt theo điều kiện validation)
> * Nút **Tiếp tục với Google** và **Tiếp tục với Apple** ở vị trí đầu tiên

> [accordion] Màn hình Nhập OTP
>
> * Input OTP 6 ô riêng biệt, tự động chuyển sang ô tiếp theo
> * Đếm ngược thời gian hiệu lực OTP
> * Nút Gửi lại OTP (chỉ khả dụng sau 1 phút)
> * Link quay lại màn hình trước
> * Hiển thị rõ phương thức OTP đang gửi đến (Email hay Số điện thoại)

> [accordion] Màn hình Đăng nhập
>
> * Nút **Tiếp tục với Google** (ở vị trí nổi bật nhất)
> * Nút **Tiếp tục với Apple**
> * Tab chuyển đổi giữa Đăng nhập Email/Mật khẩu và Đăng nhập Số Điện Thoại OTP
> * Link **Quên mật khẩu**
> * Link chuyển sang màn hình Đăng ký

> [accordion] Màn hình Quên mật khẩu
>
> * Lựa chọn phương thức khôi phục: Email / Số Điện Thoại
> * Bước 1: Nhập Email / Số điện thoại
> * Bước 2: Nhập OTP
> * Bước 3: Nhập mật khẩu mới + Xác nhận


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.