Bạn mua vé máy bay hạng phổ thông. Khi lên máy bay, bạn "vô tư" ngồi vào chỗ hạng thương gia, tiếp viên tới và nhẹ nhàng "Xin lỗi, vé của anh ngồi ở phía dưới kia".
Ở bài 68.Chúng ta đã gặp hai anh em rất dễ nhầm:
Authentication
→ "Anh là ai?"
và:
Authorization
→ "Anh được phép làm gì?"
😄
Hôm nay chúng ta tập trung vào anh thứ hai:
Authorization
Và đây là một câu chuyện rất đời thường:
Bạn đã đăng nhập thành công.
Bạn có tài khoản.
Bạn có mật khẩu đúng.
Server biết chính xác:
"Đây là user Nguyễn Văn A."
Authentication:
✅
Nhưng bạn bấm:
Xóa tài khoản của người khác.
Server:
"Khoan..."
😐
"Anh là Nguyễn Văn A thì đúng."
"Nhưng..."
"Anh có quyền xóa người khác đâu?"
🤣
Và thế là:
403 ForbiddenĐây chính là Authorization.
Authorization là gì?
Authorization là quá trình xác định người dùng hoặc hệ thống đã được xác thực có được phép thực hiện một hành động hoặc truy cập một tài nguyên cụ thể hay không.
Nói đơn giản:
Authentication = Anh là ai?
Authorization = Anh được phép làm gì?
Ví dụ:
User A → được xem sản phẩm
User A → được sửa sản phẩm của mình
User A → không được xóa user khác
Admin → được xem
Admin → được sửa
Admin → được xóa
Admin → quản lý userAuthorization thường được triển khai bằng Role, Permission, hoặc các cơ chế kiểm soát truy cập khác.
Ví dụ đời thường nhất 🏢
Hãy tưởng tượng bạn làm việc trong một công ty.
Bạn bước vào cửa.
Bảo vệ kiểm tra thẻ.
"Đúng là nhân viên công ty."
Bạn được vào.
Đó là:
Authentication.
Nhưng bạn đi lên tầng 20.
Thấy cửa:
PHÒNG SERVER
Bạn quẹt thẻ.
🚫
Cửa không mở.
Bạn hỏi:
"Tôi là nhân viên mà?"
Bảo vệ:
"Đúng."
"Nhưng anh không có quyền vào phòng Server."
🤣
Đó là:
Authorization.
Một câu nhớ cả đời 😎
Nếu bạn chỉ muốn nhớ một câu:
Authentication cho bạn vào tòa nhà. Authorization quyết định bạn được vào phòng nào.
Quá dễ.
Authentication vs Authorization
| Authentication | Authorization | |
|---|---|---|
| Câu hỏi | Anh là ai? | Anh được làm gì? |
| Kiểm tra | Danh tính | Quyền |
| Thường xảy ra | Trước | Sau Authentication |
| Ví dụ | Login | Xóa user |
| Thành công | Biết user là ai | Cho phép hành động |
| Thất bại thường gặp | 401 | 403 |
Ví dụ:
Bạn đăng nhập:
email = an@email.com
password = đúng↓
Authentication:
✅
Server biết:
user_id = 25Nhưng bạn muốn:
DELETE /api/users/30Server phải hỏi tiếp:
"User 25 có quyền xóa User 30 không?"
Nếu không:
403 Forbidden😎
401 vs 403
Đây là một trong những thứ rất đáng nhớ khi làm API.
401 Unauthorized
Hiểu đơn giản:
"Tôi chưa xác thực được anh."
Ví dụ:
GET /api/profileKhông có token.
Hoặc token không hợp lệ.
Server:
401 Unauthorized403 Forbidden
Hiểu đơn giản:
"Tôi biết anh là ai. Nhưng anh không được phép làm việc này."
Ví dụ:
DELETE /api/users/30Bạn đã đăng nhập.
Token hợp lệ.
Server biết:
User ID = 25Nhưng user 25 không có quyền Admin.
Server:
403 Forbidden"Chua thêm" 😆
Authentication giống như:
Bảo vệ hỏi CMND/ID.
Bạn đưa ra.
Bảo vệ:
"OK, đúng là anh."
Authorization giống như:
Bạn nói:
"Cho tôi vào két sắt."
Bảo vệ:
"Anh là ai?"
"Nhân viên."
"OK."
"Nhưng anh có chìa khóa két sắt không?"
🤣
Biết anh là ai không đồng nghĩa với việc anh được phép làm mọi thứ.
Đây là nguyên tắc cực kỳ quan trọng của bảo mật.
Role là gì? 👨💼
Một cách rất phổ biến để phân quyền là:
Role
tức là:
Vai trò.
Ví dụ website có:
Admin
Editor
Author
User
GuestMỗi Role có quyền khác nhau.
Ví dụ đơn giản
Website blog.
Có:
Admin 👑
Có thể:
Tạo bài
Sửa bài
Xóa bài
Quản lý userEditor ✏️
Có thể:
Tạo bài
Sửa bài
Duyệt bàiNhưng:
Không quản lý userAuthor 📝
Có thể:
Viết bài
Sửa bài của mìnhUser 👤
Có thể:
Đọc bài
Bình luậnRole không phải Permission
Đây cũng là chỗ dễ nhầm.
Role
→ Vai trò.
Permission
→ Quyền cụ thể.
Ví dụ:
Role:
Admincó thể có:
Permission:
create_post
edit_post
delete_post
manage_usersCòn:
Role:
Authorcó thể có:
create_post
edit_own_postNhìn vậy sẽ dễ hiểu hơn:
User
↓
Role
↓
Permissions
↓
ActionsVí dụ ngoài đời 🏥
Hãy tưởng tượng một bệnh viện.
Có:
Bác sĩ
Y tá
Lễ tân
Quản trị viênLễ tân có thể:
Tạo hồ sơ bệnh nhân
Xem thông tin cơ bảnNhưng không nhất thiết được:
Xem mọi dữ liệu chuyên môn
Sửa kết quả xét nghiệmBác sĩ có quyền khác.
Quản trị viên có quyền khác.
😄
Không phải cứ:
"Tôi làm trong bệnh viện."
thì:
"Tôi được xem tất cả."
Đó chính là Authorization.
Authorization trong API 🌐
Bây giờ quay lại REST API.
Giả sử:
GET /api/usersServer nhận request.
Token cho biết:
user_id = 25Authentication:
✅
Sau đó Authorization kiểm tra:
User 25
↓
Role = User
↓
Permission = view_users?Nếu:
NoServer trả:
403 ForbiddenNếu:
YesServer trả dữ liệu.
Một ví dụ nguy hiểm 😱
API có:
DELETE /api/users/50Developer mới có thể viết:
Nếu có token
→ cho xóa😨
Sai.
Vì:
Có token
chỉ chứng minh:
"Anh đã xác thực."
Nó không chứng minh:
"Anh có quyền xóa."
Đúng hơn phải là:
Có token?
↓
Authentication
↓
User là ai?
↓
Có quyền DELETE user không?
↓
YES → cho phép
NO → 403Đây là lỗi bảo mật rất nguy hiểm 🚨
Giả sử:
User A
id = 10có đơn hàng:
order_id = 100User B:
id = 20có đơn hàng:
order_id = 200User A gọi:
GET /api/orders/200Nếu Server chỉ kiểm tra:
Token hợp lệ?↓
Có.
↓
Trả đơn hàng 200.
💀
User A có thể xem đơn hàng của User B.
Server phải kiểm tra thêm
Không chỉ:
"Anh đã đăng nhập chưa?"
mà phải hỏi:
"Đơn hàng này có thuộc về anh không?"
Ví dụ ý tưởng:
User ID = 10
Order ID = 200
Order 200 thuộc User 20
→ DENYĐây chính là Authorization ở cấp độ resource.
Resource Authorization là gì?
Resource có thể hiểu đơn giản là:
Tài nguyên/dữ liệu mà user muốn truy cập.
Ví dụ:
Post
Order
Invoice
Profile
Photo
Document
ProductAuthorization phải kiểm tra:
User này có quyền thao tác với resource này không?
Ví dụ:
GET /api/orders/200Không chỉ hỏi:
"User có đăng nhập không?"
Mà hỏi:
"Order 200 có thuộc user này không?"
Một ví dụ cực thực tế với Blog 📝
Bạn có bài:
Post ID = 100
Author ID = 25User 25 gọi:
PUT /api/posts/100Server:
"Đây là bài của User 25."
→ Cho sửa.
User 30 gọi:
PUT /api/posts/100Server:
"User 30 không phải tác giả."
→ Có thể từ chối.
403 Forbidden😎
Admin thì sao?
Admin có thể có quyền đặc biệt.
Ví dụ:
Adminđược phép:
edit_any_post
delete_any_post
manage_usersTrong khi:
Authorchỉ có:
create_post
edit_own_postĐây là lý do Role + Permission rất hữu ích.
RBAC là gì? 👮
Bạn sẽ gặp thuật ngữ:
RBAC
= Role-Based Access Control
Nói đơn giản:
Phân quyền dựa trên Role.
Ví dụ:
Admin
↓
delete_user
Editor
↓
edit_post
Author
↓
create_postUser được gán Role.
Role quyết định quyền.
Đây là mô hình rất phổ biến.
ABAC là gì? 🤔
Sau này bạn có thể gặp:
ABAC
= Attribute-Based Access Control.
Thay vì chỉ hỏi:
"Anh là Admin không?"
hệ thống có thể kiểm tra nhiều thuộc tính:
User
Resource
Action
EnvironmentVí dụ:
User này có phải người phụ trách phòng ban đó không?
Tài liệu có thuộc cùng công ty không?
Đang truy cập trong giờ cho phép không?
Resource có mức bảo mật phù hợp không?
Đây là mô hình linh hoạt hơn nhưng cũng phức tạp hơn.
Với người mới:
RBAC trước.
ABAC để sau.
😄
Authorization không chỉ có Admin/User
Đây là một hiểu lầm rất phổ biến.
Nhiều người mới nghĩ:
Admin
Userlà xong.
Không hẳn.
Website thực tế có thể có:
Super Admin
Admin
Manager
Editor
Author
Moderator
Customer
Support
Guest
...Hoặc thậm chí không dùng Role cố định mà dùng Permission.
Ví dụ hệ thống bán hàng 🛒
Admin
→ quản lý tất cả
Manager
→ quản lý sản phẩm + đơn hàng
Staff
→ xử lý đơn hàng
Customer
→ xem sản phẩm + quản lý đơn của mìnhNếu Customer gọi:
DELETE /api/products/15Server:
"Không."
🤣
Frontend có thể kiểm tra quyền không?
Có thể.
Ví dụ:
Nếu user không phải Admin.
Frontend không hiển thị:
[Xóa User]Điều này tốt cho trải nghiệm người dùng.
Nhưng...
⚠️ Không được coi đó là biện pháp bảo mật chính.
Tại sao?
Vì người dùng có thể tự gọi API.
Ví dụ:
DELETE /api/users/15Họ không cần bấm nút trên giao diện.
Họ có thể dùng:
- DevTools
- Postman
- curl
- Một chương trình tự viết
😅
Vì vậy:
Authorization phải được kiểm tra ở Backend.
Đây là nguyên tắc cực kỳ quan trọng 🔥
Frontend nói:
"Tôi không cho user thấy nút Delete."
Backend vẫn phải nói:
"Tôi sẽ kiểm tra xem user có quyền Delete không."
Hai lớp:
Frontend
→ UX
Backend
→ SecurityĐừng nhầm hai thứ này.
"Chua thêm" lần 2 🤣
Bạn vào ngân hàng.
App không hiện nút:
"Rút 10 tỷ."
Bạn nghĩ:
"Vậy là an toàn rồi."
Không.
🤣
Bạn có thể tự gửi request:
POST /api/withdrawNếu Backend chỉ nghĩ:
"Frontend không có nút."
thì...
💀
Backend phải tự kiểm tra:
"User này có được phép rút số tiền này không?"
Backend mới là người gác cổng thật sự.
Authorization và HTTP Method
Authorization có thể phụ thuộc vào hành động.
Ví dụ:
GET /api/products→ User được phép xem.
Nhưng:
DELETE /api/products/15→ Chỉ Admin được phép.
Cùng một resource.
Nhưng:
Action khác nhau → Permission khác nhau.
Ví dụ Permission
Bạn có thể thiết kế:
products.view
products.create
products.update
products.deleteMột user:
products.view→ được xem.
Nhưng:
products.delete→ không có.
Authorization Matrix 📊
Một cách rất dễ hình dung:
| Role | View | Create | Update | Delete |
|---|---|---|---|---|
| Guest | ✅ | ❌ | ❌ | ❌ |
| User | ✅ | ❌ | ❌ | ❌ |
| Author | ✅ | ✅ | Own | ❌ |
| Editor | ✅ | ✅ | ✅ | ❌ |
| Admin | ✅ | ✅ | ✅ | ✅ |
Đây chính là một:
Authorization Matrix.
Nó giúp developer nhìn rõ:
Ai được làm gì?
Debug Authorization kiểu dev thật 🔍
API trả:
403 ForbiddenBạn nghĩ:
"API chết."
Không.
😄
Kiểm tra:
1. User đã đăng nhập chưa?
Nếu chưa:
→ Có thể là 401.
2. User là ai?
Kiểm tra:
user_id3. Role là gì?
Admin?
Editor?
User?4. Permission có tồn tại không?
Ví dụ:
products.delete5. Resource có thuộc user không?
Ví dụ:
order_id = 200thuộc ai?
6. Backend có thực sự kiểm tra quyền không?
Đừng chỉ nhìn Frontend.
Một lỗi rất hay gặp: IDOR 😱
Bạn có thể gặp thuật ngữ:
IDOR
= Insecure Direct Object Reference
Tên nghe rất hàn lâm.
Nhưng ý tưởng khá dễ hiểu.
Ví dụ:
Bạn đang xem:
/api/orders/100Bạn đổi thành:
/api/orders/101Nếu Server cho bạn xem dữ liệu của người khác chỉ vì bạn đổi ID...
💀
Đó là một vấn đề Authorization.
Đây là lý do:
"Có đăng nhập" chưa đủ.
Server phải kiểm tra:
User này có quyền truy cập resource này không?
Authorization và Database
Database có thể lưu:
usersVí dụ:
id | name | role
---|------|------
1 | An | admin
2 | Bình | user
3 | Cường| userBackend đọc:
user_id = 2
role = userKhi Bình gọi:
DELETE /api/users/3Backend kiểm tra:
role = userCó quyền:
delete_user?→ Không.
Trả:
403 ForbiddenNhưng đừng chỉ dựa vào Role trong Database
Ví dụ:
role = adminkhông có nghĩa Admin được phép làm mọi thứ trong mọi hệ thống.
Authorization thực tế có thể phụ thuộc vào:
- Role
- Permission
- Resource ownership
- Organization
- Subscription
- Trạng thái tài khoản
- Chính sách hệ thống
Vì vậy Authorization nên được thiết kế rõ ràng.
Authorization trong Laravel
Khi học Laravel.
Bạn sẽ gặp những công cụ như:
Middleware
Gate
Policy
Đây là những cơ chế giúp kiểm soát quyền truy cập.
Ví dụ tư duy:
Request
↓
Authentication
↓
User
↓
Authorization
↓
Policy / Permission
↓
ControllerKhông cần học thuộc tất cả ngay.
Chỉ cần nhớ:
Middleware có thể chặn request. Policy có thể giúp kiểm tra quyền đối với resource.
Sau này học Laravel sâu hơn.
Bạn sẽ thấy những thứ này rất tự nhiên.
Một nguyên tắc cực hay 💡
Hãy viết Authorization theo kiểu:
"User có được phép thực hiện ACTION trên RESOURCE này không?"
Ví dụ:
User 25
↓
EDIT
↓
Post 100Hỏi:
User 25 có được edit Post 100 không?
Nếu:
YES→ Cho phép.
Nếu:
NO→ 403.
Cách suy nghĩ này rất mạnh.
Đừng viết Authorization kiểu "cảm tính" 😅
Ví dụ:
if user_id == 1
cho phép😨
Có thể chạy.
Nhưng rất khó bảo trì.
Ngày mai:
Admin = 1Ngày kia:
Admin = 15Ngày nọ:
Có 5 AdminCode bắt đầu:
💥
Tốt hơn là xây dựng quyền theo Role/Permission/Policy rõ ràng.
Checklist chuẩn không cần chỉnh 😎
Authentication = Anh là ai?
Authorization = Anh được phép làm gì?
401 thường liên quan đến Authentication.
403 thường liên quan đến Authorization.
Role = Vai trò.
Permission = Quyền cụ thể.
RBAC = phân quyền dựa trên Role.
Backend phải kiểm tra Authorization.
Không được chỉ ẩn nút trên Frontend rồi nghĩ là an toàn.
Phải kiểm tra quyền với resource cụ thể khi cần.
User đăng nhập thành công không có nghĩa được làm mọi thứ.
Cần đặc biệt chú ý các API thao tác dữ liệu như Update/Delete.
IDOR là một ví dụ điển hình của lỗi kiểm soát quyền truy cập.
Authorization nên được thiết kế rõ ràng và nhất quán.
FAQ nhanh
Authentication và Authorization khác nhau thế nào?
→ Authentication trả lời "Anh là ai?", còn Authorization trả lời "Anh được phép làm gì?"
Đã đăng nhập thì có được phép xem mọi dữ liệu không?
→ Không. Quyền truy cập còn phụ thuộc vào Role, Permission, ownership và các chính sách của hệ thống.
401 và 403 khác nhau thế nào?
→ 401 thường có nghĩa request chưa có thông tin xác thực hợp lệ. 403 nghĩa Server biết hoặc đã xác thực người dùng nhưng từ chối vì không đủ quyền.
Frontend có thể làm Authorization không?
→ Frontend có thể ẩn/hiện chức năng để cải thiện UX, nhưng Backend phải là nơi thực thi kiểm tra quyền thực sự.
Role và Permission khác nhau thế nào?
→ Role là một nhóm vai trò như Admin hoặc Author. Permission là quyền cụ thể như delete_user hoặc edit_post.
User thường có thể tự sửa Role của mình thành Admin không?
→ Không nên. Việc thay đổi Role phải được Backend kiểm soát chặt chẽ.
IDOR có phải là lỗi Authentication không?
→ Thường đây là vấn đề Authorization/Access Control: user đã đăng nhập nhưng được phép truy cập resource mà họ không nên được phép truy cập.
Bạn có thể cũng đang gặp 😭
👉 API là gì? (Giải thích như gọi đồ ăn.)
👉 Session vs Cookie - Hai anh em dễ nhầm nhất của PHP
👉 Cookie là gì? (Vì sao website nhớ được bạn là ai?)
Tổng kết
Authorization nghe có vẻ là một thuật ngữ rất "Backend".
Nhưng thực chất nó chỉ là một câu hỏi:
"Anh được phép làm việc này không?"
😎
Server nhận request:
DELETE /api/users/50Không được chỉ hỏi:
"Anh đăng nhập chưa?"
Mà phải hỏi:
Anh là ai?
↓
User 25
↓
Anh có quyền DELETE không?
↓
Có
↓
Anh có được xóa User 50 không?
↓
Có
↓
Cho phépNếu không:
403 ForbiddenĐó chính là Authorization.
Và nếu bạn chỉ nhớ một câu:
Authentication đưa bạn qua cửa. Authorization quyết định bạn được phép mở những cánh cửa nào. 👮