# Đăng ký / đăng nhập bằng TikTok

Website mẫu dùng TikTok Login Kit (OAuth 2.0 v2). Lần đầu bấm nút là tạo tài khoản mới,
các lần sau là đăng nhập vào đúng tài khoản đó.

Yêu cầu: **Node >= 18** và một **MySQL/MariaDB**. Không có package native nào nên
không phải cài Visual Studio Build Tools, và chạy được trên cPanel (chỉ cấp Node 18–22).

## Chạy thử

```bash
npm install
copy .env.example .env    # Windows; macOS/Linux dùng `cp`. Rồi điền client key + thông tin MySQL.
npm start
```

App tự tạo 3 bảng ở lần chạy đầu, không phải import file `.sql` nào.

Mở http://localhost:3000

Chưa điền `TIKTOK_CLIENT_KEY` / `TIKTOK_CLIENT_SECRET` thì trang vẫn mở được nhưng bấm nút
sẽ bị TikTok báo lỗi client key không hợp lệ.

## Cấu hình phía TikTok

1. Vào https://developers.tiktok.com/apps, tạo app.
2. Thêm sản phẩm **Login Kit**, bật **Configure for Web**.
3. Điền Redirect URI: `https://ten-mien-cua-ban.com/auth/tiktok/callback`
   - Bắt buộc `https`, phải trùng từng ký tự với `TIKTOK_REDIRECT_URI` trong `.env`.
   - Khi dev ở máy: chạy `ngrok http 3000`, lấy domain https của ngrok dán vào cả 2 chỗ.
4. Điền Terms of Service URL và Privacy Policy URL (phải là link thật, đang online).
5. Scope: chỉ cần `user.info.basic`.
6. Submit review. App ở trạng thái *staging* chỉ đăng nhập được bằng tài khoản test
   bạn tự thêm; duyệt xong mới dùng được cho người ngoài.

## Luồng chạy

```
Người dùng bấm nút
   └─> GET /auth/tiktok
         sinh state ngẫu nhiên, lưu vào session
         redirect sang tiktok.com/v2/auth/authorize/
   └─> Người dùng bấm Authorize trên TikTok
   └─> GET /auth/tiktok/callback?code=...&state=...
         đối chiếu state (chống CSRF)
         POST /v2/oauth/token/      -> access_token + refresh_token
         GET  /v2/user/info/        -> open_id, display_name, avatar_url
         tìm open_id trong DB: chưa có -> tạo user; đã có -> đăng nhập
         set session, redirect về /
```

## Cấu trúc

| File | Việc |
|---|---|
| `server.js` | Toàn bộ luồng OAuth + API session |
| `app.cjs` | Cầu nối CommonJS cho Passenger — chỉ cPanel/Plesk cần |
| `db.js` | MySQL (`mysql2`), 2 bảng `users` và `social_accounts` |
| `session-store.js` | Session store lưu vào MySQL, phiên sống sót qua restart |
| `public/index.html` | Giao diện: nút đăng nhập, hồ sơ, form email, nút xoá tài khoản |
| `public/terms.html` | Điều khoản dịch vụ — URL khai với TikTok |
| `public/privacy.html` | Chính sách bảo mật — URL khai với TikTok |
| `TIKTOK-REVIEW.md` | Văn bản dán vào form review + checklist trước khi submit |
| `DEPLOY-CPANEL.md` | Runbook deploy lên hosting cPanel, từng bước |
| `DEPLOY.md` | Runbook deploy lên Ubuntu VPS, từng bước |
| `deploy/` | File systemd và nginx cho VPS (cPanel không dùng tới) |

## Trước khi submit review: thay placeholder

Ba file HTML trong `public/` còn `[TÊN WEBSITE]` và `[EMAIL LIÊN HỆ]`. Thay hết bằng
giá trị thật — reviewer TikTok thấy dấu ngoặc vuông là từ chối. Tìm nhanh:

```powershell
Select-String -Path public\*.html -Pattern '\[TÊN WEBSITE\]|\[EMAIL LIÊN HỆ\]'
```

Chạy đến khi lệnh này không trả về dòng nào là xong.

## Những chỗ phải sửa trước khi lên production

- ~~**Session store**~~: đã xong — `session-store.js` lưu phiên vào MySQL, restart
  không mất, chạy nhiều tiến trình cũng dùng chung được.
- **Mã hóa token**: `access_token` / `refresh_token` đang lưu thô trong DB.
  Nên mã hóa bằng KMS hoặc `crypto.createCipheriv` với khóa để ngoài DB.
- **Làm mới token**: hàm `refreshAccessToken()` đã viết sẵn nhưng chưa nối vào flow.
  Access token hết hạn sau 24 giờ, refresh token sau 365 ngày. Nếu bạn chỉ dùng
  TikTok để đăng nhập thì sau bước đầu không cần token nữa — cân nhắc revoke ngay
  và không lưu gì cả.
- **Xoá tài khoản**: `POST /api/me/delete` đã nối sẵn — gọi `revokeToken()` để thu hồi
  quyền bên TikTok rồi xoá bản ghi (`social_accounts` bay theo nhờ `ON DELETE CASCADE`).
  Đây là yêu cầu bắt buộc của TikTok Developer Terms, đừng bỏ nút này khỏi giao diện.
- **Email**: TikTok không trả email. App đang hỏi email ở bước sau khi đăng nhập —
  nên gửi mail xác thực trước khi cho dùng email đó để khôi phục tài khoản.
- **Đừng để TikTok là cách đăng nhập duy nhất.** Nếu app bị TikTok từ chối duyệt
  hoặc khóa, toàn bộ người dùng của bạn mất đường vào.
