- Tutorial của freeCodeCamp hướng dẫn build multi-user note API với Django REST Framework và SimpleJWT qua 10 bước rõ ràng.
- JWT authentication giải quyết cross-domain, mobile, và scalability - access token 30 phút, refresh token 1 ngày.
- Scoping qua override get_queryset() đảm bảo mỗi user chỉ thấy dữ liệu của mình, trả 404 thay 403 để chặn ID enumeration attack.
- Áp dụng được cho task manager, journal, bookmarks, hoặc bất kỳ app multi-user nào cần tách biệt dữ liệu.
TL;DR
Tutorial của Prabodh Tuladhar trên freeCodeCamp hướng dẫn xây dựng API ghi chú cá nhân bảo mật với Django REST Framework (DRF) và SimpleJWT. Hai khái niệm cốt lõi: JWT authentication stateless giải quyết vấn đề cross-domain và mobile client, và scoping - đảm bảo mỗi user chỉ đọc được dữ liệu của chính mình, dù có cố đoán ID người khác. Kết quả là API đầy đủ CRUD với access token 30 phút, refresh token 1 ngày, bảo mật khỏi ID enumeration attack.

Session auth không còn đủ
Django mặc định dùng session-based authentication. Cách này hoạt động ổn khi frontend và backend cùng domain. Nhưng khi tách ra - React chạy trên Netlify, Django API trên PythonAnywhere - cookie bị trình duyệt chặn do quy tắc cross-domain. Workaround bằng CORS headers thêm độ phức tạp và dễ vỡ.
Vấn đề thứ hai là hiệu năng: 10.000 user đồng thời = 10.000 lần tra cứu database mỗi request chỉ để xác thực session. Khi ứng dụng scale, đây là bottleneck thật sự. Và mobile app không xử lý cookie như browser - thêm một lớp rắc rối nữa.
JWT giải quyết cả ba: server không lưu session, chỉ xác minh chữ ký cryptographic của token. Token gửi qua HTTP header - hoạt động trên mọi domain, mọi client. Stateless, scalable, universal.
Trước khi bắt đầu
- Python 3.8+ và pip đã cài
- Hiểu Django cơ bản: models, views, URLs, migrations
- Quen với DRF: serializers, viewsets, request/response cycle
- Postman hoặc curl để test endpoint
Cài đặt trong virtual environment: pip install django djangorestframework djangorestframework-simplejwt
10 bước xây dựng API
Tutorial chia thành 10 bước tuần tự:
- Setup dự án: tạo virtual env, cài 3 package, khởi tạo Django project và app
notes, đăng ký vàoINSTALLED_APPS - Custom User Model: kế thừa
AbstractUser, setAUTH_USER_MODEL = 'notes.CustomUser'trong settings - bắt buộc TRƯỚC khi chạy migration đầu tiên - Note Model: định nghĩa model với
owner = ForeignKey(CustomUser), migrate, đăng ký Admin - Serializers:
UserSerializervớipassword write_only=Truevà overridecreate()dùngcreate_user();NoteSerializervớiowner = ReadOnlyField(source='owner.username') - Cấu hình SimpleJWT: thêm
JWTAuthenticationvàoDEFAULT_AUTHENTICATION_CLASSES,IsAuthenticatedvàoDEFAULT_PERMISSION_CLASSES, access 30 phút, refresh 1 ngày - Auth Logic:
RegisterViewkế thừagenerics.CreateAPIView, setpermission_classes = [AllowAny]để public - Scoped Views:
NoteViewSetoverrideget_queryset()filter theo user hiện tại, overrideperform_create()tự gán owner - URL Config: nối app-level và project-level URLs, thêm endpoint
/api/token/và/api/token/refresh/ - Test Postman: đăng ký user, lấy token, tạo note, kiểm tra scoping giữa 2 user
- Xử lý token hết hạn: gửi refresh token đến
/api/token/refresh/để lấy access token mới không cần đăng nhập lại
Bí kíp kỹ thuật cần nhớ
Ba pattern bảo mật then chốt trong tutorial này:
404 thay vì 403. Khi user B cố truy cập note của user A bằng cách đoán ID, API trả 404 Not Found thay vì 403 Forbidden. Lý do: 403 xác nhận "note này tồn tại nhưng bạn không có quyền" - tiết lộ thông tin cho attacker. 404 là bức tường trống - attacker không biết note có tồn tại không. Đây là cách chống ID enumeration attack chuẩn mực trong thiết kế API.
Owner tamper-proof. Serializer đặt owner = ReadOnlyField - user không thể tự set owner qua POST request. ViewSet gọi serializer.save(owner=self.request.user) - server tự gán. Hai lớp phối hợp: không thể giả mạo ownership dù gửi bất kỳ payload nào.
Custom User Model ngay từ đầu. Dùng default User model rồi sau đó muốn chuyển sang login bằng email - không làm được mà không phá migration. AbstractUser cho phép tùy chỉnh bất kỳ lúc nào sau này. Đây là best practice không nên bỏ qua dù dự án nhỏ.
Ai nên áp dụng ngay
Pattern JWT + scoping phù hợp với:
- App multi-user với dữ liệu riêng tư: ghi chú, task manager, journal, bookmarks - mỗi user chỉ thấy dữ liệu của mình
- Kiến trúc tách biệt frontend/backend: React/Vue/mobile app gọi Django API qua HTTP - JWT là lựa chọn tự nhiên
- Hệ thống cần scale: stateless auth không bottleneck ở database session lookup khi concurrent users tăng cao
- Role-based systems: clinic app với bác sĩ/bệnh nhân/lễ tân, scoping theo role thay vì chỉ theo user
Đi tiếp từ đây
Tutorial xây xong nền vững. Các bước tự nhiên tiếp theo author đề xuất:
- Thêm search với
DRF SearchFiltervàdjango-filter- hỗ trợ query?search=meeting - Thêm categories/tags qua ForeignKey hoặc ManyToManyField
- Bật token blacklisting của SimpleJWT để logout thực sự vô hiệu hóa refresh token (mặc định vẫn hợp lệ 24h sau khi user "logout")
- Deploy lên PythonAnywhere, Railway, hoặc Render với PostgreSQL và HTTPS
- Build React/Next.js frontend, implement automatic token refresh khi gặp 401
Đọc đầy đủ tutorial tại freeCodeCamp. Tham khảo thêm: Django REST Framework Authentication docs và SimpleJWT Getting Started.
