📌 Mục lục
- Vì sao phải học bảo mật?
- RBAC là gì? — Câu chuyện tòa nhà văn phòng
- RLS là gì? — Câu chuyện tủ hồ sơ cá nhân
- RBAC vs RLS — Khi nào dùng cái nào?
- Firebase Auth — Cổng vào tòa nhà
- Firestore Security Rules — Bảo vệ tủ hồ sơ
- Áp dụng vào ProjectOS — Ai làm được gì?
- Thư viện Prompt mẫu cho Claude Code
- Thực hành: 5 bài tập có lời giải prompt
- Checklist kiểm tra sau khi Claude Code viết xong
1. Vì sao phải học bảo mật?
Hãy tưởng tượng bạn vừa thuê Claude Code xây xong ứng dụng ProjectOS. App chạy ngon, đẹp, ai cũng vào được. Nhưng có vấn đề:- 👤 Một nhân viên thử vọc → vô tình xoá toàn bộ task của Giám đốc.
- 🕵️ Một thực tập sinh tò mò → đọc được bảng lương của cả công ty.
- 😈 Một cựu nhân viên (vẫn còn tài khoản) → sửa ngân sách dự án từ ở nhà.
2. RBAC là gì?
🏢 Câu chuyện toà nhà văn phòng
Hãy hình dung công ty SOFTECH có một toà nhà 10 tầng:- Tầng 1 — Sảnh: Ai cũng vào được.
- Tầng 2-5 — Văn phòng nhân viên: Cần thẻ nhân viên.
- Tầng 6-8 — Phòng họp & tài liệu mật: Cần thẻ trưởng phòng trở lên.
- Tầng 9 — Phòng tài chính: Chỉ kế toán + giám đốc.
- Tầng 10 — Phòng giám đốc: Chỉ giám đốc.
Đó chính là RBAC. Mỗi người được gán một vai trò (role), và mỗi vai trò có một danh sách quyền cố định.
🎯 RBAC trong app
Áp dụng vào ProjectOS:🗝️ Role được lưu ở đâu?
Trong Firebase, role thường được lưu ở 2 nơi:- Custom Claims (gắn vào tài khoản Auth) — Cách “xịn”, không sửa được từ trình duyệt.
- Document
users/{userId}trong Firestore — Dễ làm, nhưng phải viết luật cẩn thận để người dùng không tự sửa role của mình.
💬 Khi prompt Claude Code, bạn chỉ cần nói: “Lưu role ở custom claims” hoặc “Lưu role trong collection users” — Claude sẽ tự chọn cách triển khai.
3. RLS là gì?
📁 Câu chuyện tủ hồ sơ cá nhân
Quay lại toà nhà SOFTECH. Bạn là nhân viên (member), bạn đã lên được tầng 3. Trong phòng có 100 tủ hồ sơ — mỗi tủ là một task của một người khác nhau.
- Bạn chỉ được mở tủ của chính bạn (task
assignee = bạn). - Bạn không được mở tủ của anh A ngồi cạnh — dù bạn đã vào được tầng.
🔍 RLS trả lời câu hỏi gì?
💡 Sự khác biệt mấu chốt
4. RBAC vs RLS
Trong thực tế, luôn dùng cả hai cùng lúc. Đây là cách kết hợp: Khi Tùng gọi Firestore, Firebase tự đọcrole: manager từ vé.
💬 Prompt mẫu để Claude Code thiết lập custom claims:
Tôi cần một Firebase Cloud Function để admin có thể gánrole(viewer,member,manager,finance,admin) cho user khác qua custom claims. Yêu cầu:
- Chỉ user có
role == adminmới gọi được function này.- Function nhận
targetUserIdvànewRole.- Validate
newRolephải nằm trong danh sách cho phép.- Cập nhật cả custom claim VÀ document
users/{targetUserId}.roleđể FE đọc nhanh.- Viết theo Cloud Functions v2 (
onCall), TypeScript, có log audit.
6. Firestore Security Rules
Đây là “bộ luật” mà Firebase đọc mỗi khi có ai cố đọc/ghi dữ liệu. Nó được viết bằng một ngôn ngữ riêng (gần giống JavaScript) và lưu trong filefirestore.rules.
📜 Cấu trúc cơ bản
🔍 Bóc tách từng dòng
⚠️ 3 cái bẫy hay gặp
-
request.resourcevsresource— Lẫn lộn 2 cái này = mở toang cửa.resource= dữ liệu đã có trong DB.request.resource= dữ liệu người dùng muốn ghi vào.
-
Quên kiểm tra trường nhạy cảm khi update.
Ví dụ: Cho member sửa task — nhưng không cấm họ tự đổi
rolethànhadmin. -
Cho client tự ghi role. Nếu role lưu trong Firestore và bạn cho user update document
users/{me}, họ có thể tự thăng chức! → Luôn dùngrequest.resource.data.role == resource.data.roleđể cấm thay đổi.
7. Áp dụng vào ProjectOS
Đây là ma trận quyền đầy đủ cho ProjectOS. Đưa bảng này cho Claude Code, nó sẽ viết được rules.📊 Bảng quyền
Ghi chú ký hiệu: 👁️ đọc | ✏️ ghi/sửa | 🗑️ xoá | ❌ chặn hoàn toàn
🔑 Quy tắc đặc biệt
roletrongusers/{uid}— không user nào tự sửa được, kể cả chính họ. Chỉ admin qua Cloud Function.- Budget — bị chặn hoàn toàn với viewer/member (kể cả đọc).
- Activity log — chỉ Cloud Function được ghi, FE chỉ đọc.
8. Thư viện Prompt mẫu
Đây là 8 prompt sẵn dùng — copy-paste vào Claude Code khi bạn cần.📝 Prompt 1 — Thiết lập role system ban đầu
📝 Prompt 2 — Viết Firestore Rules tổng thể
📝 Prompt 3 — Cloud Function gán role
📝 Prompt 4 — Test rules bằng Emulator
📝 Prompt 5 — UI: Ẩn nút theo role
📝 Prompt 6 — Phát hiện rò rỉ quyền
📝 Prompt 7 — Audit log
📝 Prompt 8 — Migrate role cũ
9. Thực hành
Đây là 5 bài tập có lời giải prompt. Học viên đọc đề → tự nghĩ cách diễn đạt → so sánh với prompt mẫu.
🎯 Bài 1 — Cấm intern xem lương
Đề: Trong ProjectOS có module Team, mỗi member có fieldsalary. Bạn muốn:
- Member chỉ xem được lương của chính mình.
- Manager xem được lương của mọi người trong team.
- Finance/Admin xem được tất cả.
🎯 Bài 2 — Một user vừa là member dự án A, vừa là manager dự án B
Đề: ProjectOS hiện đang single-project. Sau này khi mở rộng multi-project, một user có thể có role khác nhau ở từng dự án. Prompt gợi ý:🎯 Bài 3 — Cho phép guest xem dashboard public
Đề: Bạn muốn có một trang/public/{projectId} mà ai (kể cả chưa login) cũng xem được — nhưng chỉ thấy số liệu tổng quan, không thấy task chi tiết.
Prompt gợi ý:
🎯 Bài 4 — Xoá task chỉ trong 5 phút sau khi tạo
Đề: Để chống “lỡ tay”, chỉ cho phép xoá task trong vòng 5 phút sau khi tạo, và chỉ bởi người tạo. Sau 5 phút, chỉ manager mới xoá được. Prompt gợi ý:🎯 Bài 5 — Khoá tài khoản tạm thời
Đề: Khi một nhân viên bị nghỉ phép kỷ luật, admin muốn vô hiệu hoá tài khoản mà không xoá data. Prompt gợi ý:10. Checklist kiểm tra
Sau khi Claude Code viết xong, luôn chạy checklist này trước khi deploy:✅ Checklist bảo mật Firestore
- Default deny: File
firestore.rulescó dòngallow read, write: if false;ở cuối không? - Không có
allow read, write: if trueở bất kỳ đâu (trừ khi có lý do rất rõ). - Trường
roletrongusers/{uid}không thể bị client tự sửa (test bằng emulator). - Custom claims được set qua Cloud Function, không qua FE.
- Mọi collection đều có rule explicit (không rơi vào “không có rule = mở toang”).
- Phân biệt
resourcevsrequest.resourcetrong update rules. - Index đã tạo cho mọi query có
where + orderBy(chạy app, đọc warning ở console). - Test với emulator cho ít nhất 5 kịch bản chính (xem Prompt 4).
- Audit log đang ghi cho hành động nhạy cảm (đổi role, sửa budget…).
- UI guard đồng bộ với Rules — không có nút “Delete” mà rule lại từ chối (gây confused UX).
⚠️ Cảnh báo cuối: Rules không thay thế UI
Có người tưởng “tôi đã ẩn nút Delete ở UI, rule không cần lo”. SAI HOÀN TOÀN. → Bất kỳ ai cũng có thể mở DevTools, gọi Firestore SDK trực tiếp từ console, bypass UI. → Rules là tuyến phòng thủ THẬT. UI guard chỉ là UX cho người dùng tốt bụng.🎓 Tóm tắt 1 trang
RBAC = “Bạn là ai?” → role: viewer/member/manager/finance/admin
RLS = “Cái này có phải của bạn không?” → so sánh uid với field trong document
Firebase Auth = cấp ID Token + Custom Claims (vé có ghi role)
Firestore Rules = bộ luật ở server, đọc vé + kiểm tra điều kiện
Cloud Functions = nơi duy nhất an toàn để gán/thay đổi role
Quy trình prompt Claude Code:
- Mô tả ai được làm gì với dữ liệu nào (dạng bảng càng tốt).
- Yêu cầu Claude đề xuất 2-3 phương án trước khi code.
- Sau khi code xong, yêu cầu Claude viết test bằng emulator.
- Chạy checklist 10 mục ở mục 10.
- KHÔNG BAO GIỜ deploy rules mới mà chưa test bằng emulator.
Tài liệu kèm theo trong repo ProjectOS:Chúc bạn xây ProjectOS an toàn! 🔐
.claude/docs/auth.md— Auth flow chi tiết.claude/docs/firebase.md— Schema thực tế.claude/agents/firebase-expert.md— Agent chuyên Firestore