Dù đã, đang hay chuẩn bị đi làm, chúng ta có lẽ đều biết chiếc thẻ nhân viên.
Ở bài 67.Chúng ta vừa cho Frontend và Backend nói chuyện với nhau bằng REST API.
Ví dụ:
GET /api/products
Frontend hỏi:
"Cho tôi danh sách sản phẩm."
Backend:
"Đây."
😄
Quá đơn giản.
Nhưng...
Nếu API này chứa:
- Thông tin tài khoản
- Đơn hàng
- Số dư
- Hồ sơ khách hàng
- Dữ liệu cá nhân
thì có một vấn đề rất lớn:
Server làm sao biết người đang gọi API là ai? 🤔
Nếu bất kỳ ai cũng có thể gọi:
GET /api/my-orders
thì...
Người A có thể xem đơn hàng của người B.
💀
Đây chính là lúc API Authentication xuất hiện.
API Authentication là gì?
API Authentication là quá trình xác thực danh tính của người dùng hoặc ứng dụng trước khi Server cho phép truy cập vào các API được bảo vệ.
Nói đơn giản:
Authentication = "Anh là ai?"
Server cần một cách để kiểm tra:
"Anh có đúng là người mà anh nói mình là không?"
Sau khi xác thực thành công, Server mới có thể cho phép truy cập vào những dữ liệu hoặc chức năng tương ứng.
Ví dụ đời thường nhất 🏢
Hãy tưởng tượng bạn đi vào một tòa nhà văn phòng.
Bạn bước tới cửa.
Bảo vệ hỏi:
"Anh là ai?"
Bạn trả lời:
"Tôi là nhân viên công ty."
Bảo vệ:
"Thẻ nhân viên đâu?"
Bạn đưa thẻ.
🪪
Bảo vệ kiểm tra.
"OK. Anh là Nguyễn Văn A."
Cửa mở.
🚪
Đây chính là:
Authentication.
Nhưng chưa hết.
Bạn đi tiếp vào tầng 10.
Có một phòng ghi:
Phòng Giám đốc
Bạn thử mở cửa.
🚫
Bảo vệ nói:
"Anh đã xác thực rồi."
"Nhưng anh không có quyền vào phòng này."
Đây là:
Authorization.
Authentication vs Authorization
Hai từ này cực kỳ dễ nhầm. 😵
Nhưng chỉ cần nhớ một câu:
Authentication
Anh là ai?
Authorization
Anh được phép làm gì?
😎
Ví dụ:
Bạn đăng nhập thành công.
↓
Server biết:
"Đây là user ID 25."
Authentication → OK.
Nhưng bạn muốn xóa tài khoản của người khác.
↓
Server kiểm tra:
"User 25 có quyền Admin không?"
Nếu không:
🚫
Authorization → FAIL.
API cần Authentication để làm gì?
Không phải API nào cũng cần.
Ví dụ:
GET /api/products
Danh sách sản phẩm công khai.
Có thể không cần đăng nhập.
Nhưng:
GET /api/profile
thì khác.
Server cần biết:
"Profile của ai?"
Hoặc:
GET /api/my-orders
Server phải biết:
"Đơn hàng của user nào?"
Hoặc:
DELETE /api/products/15
Đây càng nguy hiểm.
Server phải biết:
"Ai đang muốn xóa sản phẩm?"
"Người này có quyền xóa không?"
Authentication hoạt động thế nào?
Một quy trình đơn giản có thể là:
Người dùng↓Đăng nhập↓Server kiểm tra↓Đúng?↓Tạo thông tin xác thực↓Client lưu thông tin đó↓Gọi API↓Server kiểm tra↓Cho phép / Từ chối
😄
Nói nôm na:
Đăng nhập một lần → nhận "vé" → dùng vé để gọi API.
Ví dụ với Login 🔐
Bạn nhập:
Email:an@email.comPassword:123456
Frontend gửi:
POST /api/login
kèm dữ liệu.
{"email": "an@email.com","password": "123456"}
Backend kiểm tra Database.
Nếu đúng.
Server có thể trả:
{"message": "Login successful","token": "abc123..."}
Client nhận:
"À, Server cho mình một token."
😄
Từ đây.
Khi gọi API cần bảo vệ:
GET /api/profile
Client gửi token.
Ví dụ:
Authorization: Bearer abc123...
Server kiểm tra token.
Nếu hợp lệ:
"OK. Đây là user A."
↓
Cho phép truy cập.
Token là gì? 🎫
Bạn có thể tưởng tượng token như:
Một chiếc vé điện tử.
🎫
Bạn vào công viên.
Nhân viên kiểm tra vé.
Nếu vé hợp lệ:
"Mời vào."
Nếu vé hết hạn:
"Xin lỗi."
Nếu vé giả:
"Mời ra ngoài." 😅
API Token cũng tương tự.
Server không muốn mỗi lần bạn gọi API lại bắt bạn gửi:
Password
Vì vậy sau khi đăng nhập.
Server có thể cấp một token.
Client dùng token đó trong những request tiếp theo.
Bearer Token là gì?
Bạn sẽ gặp dòng này rất nhiều khi làm API:
Authorization: Bearer abc123...
Trong đó:
Authorization
là HTTP header.
Bearer
cho biết kiểu authentication scheme.
Còn:
abc123...
là token.
Hiểu đơn giản:
"Tôi mang theo chiếc vé này."
🎫
Server:
"Để tôi kiểm tra."
Token có phải mật khẩu không?
Không.
😄
Token và password có vai trò khác nhau.
Password
→ Người dùng biết.
Token
→ Server cấp sau khi xác thực.
Ví dụ:
Email + Password↓Login↓Token↓Gọi API
Thông thường bạn không muốn gửi password trong mọi request API.
Thay vào đó.
Bạn sử dụng cơ chế xác thực phù hợp như token hoặc session.
Session có dùng cho API được không?
Có.
Đây là chỗ bài 52:
Session vs Cookie
bắt đầu quay lại.
😄
Một ứng dụng web truyền thống có thể dùng:
Session + Cookie
Người dùng đăng nhập.
↓
Server tạo Session.
↓
Browser giữ Session ID trong Cookie.
↓
Các request tiếp theo gửi Cookie.
↓
Server biết:
"À, đây là user 25."
Token và Session có giống nhau không?
Không.
Có thể hiểu đơn giản:
Session
Server giữ thông tin phiên đăng nhập.
Browser↓Cookie↓Session ID↓Server
Token
Client giữ token và gửi token trong request.
Client↓Authorization: Bearer ...↓Server
Cả hai đều có thể được dùng để xác thực.
Nhưng cách triển khai và quản lý khác nhau.
JWT là gì? 🪪
Bạn sẽ rất dễ gặp một cái tên khác:
JWT
JSON Web Token.
😄
JWT là một định dạng token phổ biến được sử dụng trong nhiều hệ thống Authentication.
Một JWT thường có dạng:
xxxxx.yyyyy.zzzzz
Ba phần được ngăn cách bởi dấu chấm.
JWT thường chứa các thông tin gọi là claims, chẳng hạn như:
{"user_id": 25}
và được ký để Server có thể kiểm tra tính hợp lệ.
Nhưng đừng hiểu JWT là "mật khẩu mã hóa" 😅
Đây là một hiểu lầm khá phổ biến.
JWT không đơn giản là:
"Mã hóa password thành một chuỗi."
Không.
JWT chủ yếu liên quan đến:
Mang thông tin + chữ ký để xác minh.
Và dữ liệu trong JWT không nên được coi là bí mật chỉ vì nó nằm trong token.
Vì vậy:
Đừng nhét password hoặc thông tin nhạy cảm vào JWT.
API Key là gì? 🔑
Bạn cũng sẽ gặp:
API Key.
Ví dụ:
X-API-Key: abc123...
API Key thường được dùng để nhận diện ứng dụng hoặc client.
Ví dụ:
Một dịch vụ cung cấp API thời tiết.
Bạn đăng ký.
↓
Dịch vụ cấp:
API Key
↓
Ứng dụng của bạn dùng Key để gọi API.
API Key và User Token có giống nhau không?
Không nhất thiết.
Có thể hiểu đơn giản:
API Key
→ Thường nhận diện ứng dụng/client.
User Token
→ Thường đại diện cho một người dùng hoặc phiên truy cập đã xác thực.
Tùy hệ thống.
Cách sử dụng có thể khác nhau.
"Chua thêm" 😆
Authentication thực ra giống đi vào quán bar.
🚪
Bảo vệ:
"ID đâu?"
Bạn:
"Đây."
Bảo vệ:
"OK. Anh là ai?"
→ Authentication.
Bạn bước vào.
Thấy một cánh cửa:
VIP ONLY
Bạn định mở.
Bảo vệ:
"Anh có quyền vào không?"
→ Authorization.
🤣
Vậy:
Authentication = kiểm tra danh tính.
Authorization = kiểm tra quyền hạn.
Hai anh em này cực kỳ dễ bị gọi nhầm.
Một lỗi cực kỳ nguy hiểm 😱
Giả sử API có:
GET /api/orders/25
Bạn đăng nhập bằng user ID 10.
Nhưng bạn thay URL thành:
GET /api/orders/26
Nếu Server trả về đơn hàng của user khác...
💀
Website có vấn đề bảo mật.
Tại sao?
Vì Server đã kiểm tra:
"User này đã đăng nhập."
Nhưng chưa kiểm tra:
"User này có quyền xem đơn hàng này không?"
Đây là khác biệt rất quan trọng giữa:
Authentication
và
Authorization.
Đăng nhập thành công không có nghĩa là được làm mọi thứ
Ví dụ:
User thường
đăng nhập thành công.
Authentication:
✅
Nhưng người này thử:
DELETE /api/users/15
Server phải hỏi:
"User này có quyền xóa user không?"
Nếu không:
403 Forbidden
Đây là:
Authorization thất bại.
API Authentication và HTTPS 🔒
Có một điều cực kỳ quan trọng.
Nếu bạn gửi thông tin xác thực qua kết nối không an toàn...
😨
Kẻ xấu có thể có cơ hội đánh cắp thông tin.
Vì vậy các API thực tế cần sử dụng:
HTTPS
để mã hóa kết nối giữa Client và Server.
Nhớ bài 57 không?
😄
HTTP
→ Dữ liệu truyền đi không được bảo vệ bằng TLS.
HTTPS
→ Kết nối được bảo vệ bằng TLS.
Vì vậy:
Authentication + HTTPS
là một cặp rất quan trọng.
Token có thể bị đánh cắp không?
Có.
😐
Token không phải phép thuật.
Nếu attacker lấy được token hợp lệ.
Họ có thể có khả năng sử dụng nó như người sở hữu token, tùy hệ thống.
Vì vậy phải chú ý:
✔ HTTPS
✔ Không đưa token vào URL nếu không cần thiết
✔ Không commit token vào Git
✔ Không đưa secret lên JavaScript public
✔ Có thời hạn token phù hợp
✔ Có cơ chế thu hồi khi cần
✔ Bảo vệ nơi lưu token
Một lỗi newbie rất hay gặp 🤦
Bạn viết:
const token = "abc123...";
rồi đưa code lên GitHub.
😨
Sau đó:
"Ủa sao API bị gọi lung tung?"
🤣
Token/secret là thứ cần được bảo vệ.
Không nên đưa credential thật vào source code public.
Environment Variable là gì?
Đây là lý do bạn sẽ gặp những dòng kiểu:
API_KEY=...DB_PASSWORD=...JWT_SECRET=...
trong:
.env
Thay vì viết thẳng:
$apiKey = "abc123...";
Bạn có thể đọc giá trị từ Environment Variable.
Mục tiêu là:
Tách secret khỏi source code.
Nhưng nhớ:
.envkhông phải cái két sắt thần kỳ.
Nó vẫn phải được bảo vệ và cấu hình đúng trên Server.
Debug Authentication kiểu dev thật 😎
API báo:
401 Unauthorized
Đừng vội sửa Database.
Hãy kiểm tra:
1. Bạn đã gửi credential chưa?
Token?
Cookie?
API Key?
2. Token có đúng không?
Copy nhầm một ký tự cũng đủ lỗi.
😅
3. Token còn hạn không?
Token có thể hết hạn.
4. Header có đúng không?
Ví dụ:
Authorization: Bearer abc123
Đừng biến thành:
Authorization: abc123
nếu API yêu cầu Bearer.
5. API có yêu cầu API Key không?
Một số API cần:
X-API-Key: ...
6. Bạn đang gặp 401 hay 403?
Đây là điểm rất quan trọng.
401
→ Chưa xác thực hợp lệ.
403
→ Server biết bạn là ai nhưng bạn không được phép làm việc đó.
Nhìn Status Code để đoán bệnh 🚑
| Status | Hiểu đơn giản |
|---|---|
| 200 | Thành công |
| 201 | Đã tạo |
| 400 | Request có vấn đề |
| 401 | Chưa xác thực hợp lệ |
| 403 | Không có quyền |
| 404 | Không tìm thấy |
| 500 | Server gặp lỗi |
Ví dụ:
GET /api/profile→ 401
Nghĩ:
"Token/login có vấn đề."
Còn:
DELETE /api/users/15→ 403
Nghĩ:
"Tôi đã đăng nhập nhưng không đủ quyền."
😎
Một mẹo cực hay: DevTools → Network 🔍
Khi API Authentication bị lỗi.
Mở:
DevTools → Network
Kiểm tra:
Request Headers
Bạn có thấy:
Authorization
không?
Nếu dùng Cookie.
Có Cookie được gửi không?
Response là:
401
hay:
403
?
Response body nói gì?
Đây là cách debug tốt hơn rất nhiều so với:
"Em thử đăng nhập lại rồi mà vẫn lỗi."
🤣
Authentication trong Laravel
Nếu sau này bạn học Laravel sâu hơn.
Bạn sẽ gặp nhiều cách xác thực khác nhau.
Ví dụ:
- Session-based authentication
- API tokens
- Sanctum
- Passport
- OAuth2 trong các hệ thống phù hợp
Điều quan trọng lúc này không phải học thuộc tất cả.
Hãy hiểu nguyên lý:
Login↓Authenticate↓Credential / Token / Session↓Request API↓Server kiểm tra↓Authentication↓Authorization↓Response
Khi hiểu luồng này.
Bạn học Framework nào cũng dễ hơn.
Checklist chuẩn không cần chỉnh 😎
- Authentication = Anh là ai?
- Authorization = Anh được phép làm gì?
- API có thể dùng Session, Cookie, Token hoặc API Key tùy hệ thống
- Bearer Token thường được gửi trong
Authorizationheader - JWT là một dạng token phổ biến
- API Key thường dùng để nhận diện ứng dụng/client
- Không đưa password hoặc secret vào nơi công khai
- Không commit token thật lên GitHub
- API cần dữ liệu nhạy cảm nên sử dụng HTTPS
- 401 và 403 không giống nhau
- Luôn kiểm tra quyền truy cập vào từng resource, không chỉ kiểm tra "đã đăng nhập"
FAQ nhanh
Authentication và Authorization khác nhau thế nào?
→ Authentication xác minh bạn là ai. Authorization xác định bạn được phép làm gì.
API có bắt buộc phải dùng JWT không?
→ Không. JWT chỉ là một trong nhiều cách triển khai Authentication.
API có bắt buộc phải dùng Token không?
→ Không. Tùy hệ thống có thể sử dụng Session/Cookie, API Key, Token hoặc các cơ chế khác.
401 và 403 khác nhau thế nào?
→ 401 thường có nghĩa thông tin xác thực chưa hợp lệ hoặc chưa được cung cấp. 403 có nghĩa Server hiểu request nhưng từ chối vì bạn không có quyền.
Có thể gửi password trong mọi API request không?
→ Không nên. Thông thường người dùng xác thực một lần rồi sử dụng cơ chế phiên/token phù hợp cho các request tiếp theo.
Có HTTPS rồi thì API chắc chắn an toàn?
→ Không. HTTPS bảo vệ kết nối, nhưng API vẫn cần Authentication, Authorization, Validation, chống tấn công và nhiều biện pháp bảo mật khác.
Bạn có thể cũng đang gặp 😭
👉 REST API là gì? (GET, POST, PUT, DELETE nói chuyện với nhau như thế nào?)
👉 API là gì? (Giải thích như gọi đồ ăn.)
👉 JSON là gì? (Tại sao API gần như lúc nào cũng trả về JSON?)
👉 HTTP vs HTTPS là gì? (Vì sao trình duyệt hiện "Not Secure"?)
👉 CRUD là gì? (4 thao tác mà gần như website nào cũng phải làm với Database)
👉 MVC là gì? (Ai nhận order, ai nấu ăn và ai mang món ra?)
👉 Framework là gì? (Tại sao ai cũng thích dùng Laravel thay vì viết mọi thứ từ đầu?)
Tổng kết
Hãy quay lại câu hỏi ban đầu:
"Làm sao Server biết 'anh là ai' trước khi cho anh lấy dữ liệu?"
Câu trả lời là:
Authentication. 🔐
Bạn đăng nhập.
↓
Server xác minh.
↓
Server cấp hoặc duy trì một cơ chế xác thực.
↓
Bạn gọi API.
↓
Server kiểm tra.
↓
Nếu hợp lệ:
"OK. Mời vào."
Nếu không:
"Xin lỗi. Không biết anh là ai." 😅
Nhưng còn một câu hỏi quan trọng hơn:
"Biết anh là ai rồi thì anh được phép làm gì?"
Đó là:
Authorization.
Và đây chính là điểm mà bảo mật API bắt đầu trở nên thú vị.
Nếu chỉ nhớ hai câu:
Authentication = Anh là ai?
Authorization = Anh được phép làm gì?
thì bạn đã tránh được một trong những nhầm lẫn phổ biến nhất khi mới học Backend.
🔐 Biết người dùng là ai chưa đủ. Server còn phải biết người đó được phép làm gì.