Mở đầu#
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Nhưng chính xác thì Bearer Token là gì? Tại sao nó lại có mặt trong hầu hết mọi hệ thống API hiện đại? Từ “Bearer” mang ý nghĩa gì trong ngữ cảnh bảo mật? Và quan trọng nhất — làm thế nào để sử dụng nó một cách an toàn?
Bài viết này sẽ giải đáp toàn bộ những câu hỏi đó, từ khái niệm cơ bản đến các best practice triển khai trong thực tế.
Bearer Token là gì?#
Định nghĩa#
Bearer Token là một chuỗi token được sử dụng trong cơ chế Bearer Authentication — một phương thức xác thực HTTP được định nghĩa trong RFC 6750. Từ “Bearer” (người mang, người cầm) hàm ý rằng: bất kỳ ai “cầm” (sở hữu) token này đều có quyền truy cập tài nguyên tương ứng.
Nói cách khác, Bearer Token giống như một chiếc chìa khóa: không quan trọng bạn là ai, chỉ cần bạn có chìa khóa, bạn có thể mở cửa.
Cấu trúc HTTP Header#
Bearer Token được gửi trong HTTP request header với cú pháp:
GET /api/users HTTP/1.1
Host: api.example.com
Authorization: Bearer <token>
Trong đó:
Authorizationlà tên header.Bearerlà scheme (lược đồ xác thực), chỉ định rằng token này thuộc loại Bearer.<token>là chuỗi token thực tế, thường là một JWT (JSON Web Token), opaque token, hoặc bất kỳ định dạng token nào khác.
Ví dụ thực tế#
Khi bạn đăng nhập vào một ứng dụng, server sẽ kiểm tra thông tin đăng nhập và trả về một Bearer Token:
{
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abcd1234",
"token_type": "Bearer",
"expires_in": 3600
}
Sau đó, client lưu token này và đính kèm trong mọi request tiếp theo:
fetch('https://api.example.com/profile', {
headers: {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abcd1234'
}
})
Server nhận request, trích xuất token từ header, xác thực token, và trả về dữ liệu nếu token hợp lệ.
Lịch sử và bối cảnh ra đời#
Trước Bearer Token: Basic Authentication#
Trước khi Bearer Token trở nên phổ biến, HTTP Basic Authentication là phương thức xác thực chính:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Chuỗi dXNlcm5hbWU6cGFzc3dvcmQ= chỉ đơn giản là Base64 của username:password. Điều này có nghĩa là username và password được gửi đi trong mỗi request.
Nhược điểm rõ ràng:
- Password bị lộ nếu không dùng HTTPS (Base64 không phải là mã hóa).
- Password phải được lưu ở client (bảo mật kém).
- Không có cơ chế hết hạn tự nhiên.
- Không hỗ trợ phân quyền chi tiết (scopes).
Sự ra đời của Bearer Token (RFC 6750)#
RFC 6750 — “The OAuth 2.0 Authorization Framework: Bearer Token Usage” được công bố vào tháng 10 năm 2012, là một phần của hệ sinh thái OAuth 2.0. Nó định nghĩa cách sử dụng Bearer Token như một phương tiện xác thực trong HTTP request.
Bearer Token khắc phục hầu hết các hạn chế của Basic Auth:
- Token có thể hết hạn và được làm mới (refresh).
- Token có thể chứa thông tin phân quyền (scopes).
- Password không bị lộ trong mỗi request.
- Token có thể bị thu hồi (revoke) mà không cần đổi password.
Cách Bearer Token hoạt động#
Luồng xác thực cơ bản#
Client Authorization Server Resource Server
| | |
|--(1) Đăng nhập------------->| |
| POST /login | |
| | |
|<-(2) Bearer Token-----------| |
| {access_token: "xyz"} | |
| | |
|--(3) Request + Token------------------------------------->|
| GET /data |
| Authorization: Bearer xyz |
| |
|<-(4) Response-----------------------------------------------|
| 200 OK + data |
Bước 1-2: Lấy token (Authentication)#
Client gửi thông tin đăng nhập (username/password, social login, v.v.) đến Authorization Server. Server xác thực và trả về một Bearer Token.
Bước 3: Gửi token trong request#
Client gửi Bearer Token trong header Authorization của mọi request đến Resource Server.
Bước 4: Server xác thực token#
Resource Server nhận request, trích xuất token, và thực hiện các bước kiểm tra:
- Token có tồn tại không? — Header
Authorizationcó được gửi không? - Token có đúng định dạng không? — Có bắt đầu bằng
Bearerkhông? - Token có hợp lệ không? — Chữ ký (nếu là JWT) có đúng không?
- Token có hết hạn không? —
expclaim có nhỏ hơn thời gian hiện tại không? - Token có bị thu hồi không? — Có trong blacklist không?
- Token có đủ quyền không? — Scopes có bao gồm quyền cần thiết không?
Nếu tất cả đều hợp lệ, server trả về dữ liệu được yêu cầu.
Bearer Token và JWT#
Mối quan hệ#
Đây là một trong những điểm thường gây nhầm lẫn nhất: Bearer Token và JWT không phải là một.
| Đặc điểm | Bearer Token | JWT |
|---|---|---|
| Là gì | Phương thức xác thực (cách dùng token) | Định dạng token (cấu trúc token) |
| Định nghĩa bởi | RFC 6750 | RFC 7519 |
| Phạm vi | Cách gửi token qua HTTP | Cách mã hóa thông tin trong token |
| Có thể kết hợp? | Có | Có |
Nói cách khác:
- Bearer Token trả lời câu hỏi: “Làm thế nào để gửi token trong HTTP request?”
- JWT trả lời câu hỏi: “Làm thế nào để mã hóa thông tin vào trong token?”
Bạn có thể sử dụng JWT làm Bearer Token (phổ biến nhất), hoặc sử dụng opaque token (một chuỗi ngẫu nhiên không chứa thông tin) — cả hai đều là Bearer Token miễn là được gửi trong header Authorization: Bearer <token>.
JWT làm Bearer Token#
Đây là trường hợp phổ biến nhất. JWT gồm 3 phần, phân cách bởi dấu chấm:
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abcd1234
|------- Header -------|------ Payload ------|-- Signature --|
- Header: Thuật toán ký (HS256, RS256, v.v.).
- Payload: Thông tin claims (userId, role, exp, iat, v.v.).
- Signature: Chữ ký xác thực, đảm bảo token không bị chỉnh sửa.
Ưu điểm của JWT Bearer Token:
- Stateless: Server không cần lưu session; mọi thông tin cần thiết đã có trong token.
- Tự chứa (self-contained): Token tự mang theo thông tin người dùng và phân quyền.
- Có thể giải mã: Client có thể đọc payload để lấy thông tin cơ bản.
Opaque Token làm Bearer Token#
Opaque Token là một chuỗi ngẫu nhiên không chứa thông tin bên trong:
Authorization: Bearer abc12x9f3a7b1cde4f5
Khi server nhận được opaque token, nó phải gọi đến Authorization Server (introspection) để kiểm tra token này có hợp lệ không và lấy thông tin liên quan.
So sánh:
| Tiêu chí | JWT Bearer | Opaque Bearer |
|---|---|---|
| Tốc độ xác thực | Nhanh (không cần gọi mạng) | Chậm hơn (cần introspection) |
| Thu hồi token | Khó (cần blacklist) | Dễ (xóa khỏi DB) |
| Kích thước | Lớn hơn (chứa claims) | Nhỏ |
| Thông tin trong token | Có thể đọc được | Không thể đọc |
Bearer Token trong OAuth 2.0#
Vai trò trong hệ sinh thái OAuth 2.0#
Bearer Token là một phần không thể thiếu của OAuth 2.0 — framework ủy quyền (authorization) phổ biến nhất hiện nay. Trong OAuth 2.0, sau khi người dùng ủy quyền cho ứng dụng, Authorization Server cấp một access token (thường là Bearer Token) để ứng dụng thay mặt người dùng truy cập tài nguyên.
Các loại token trong OAuth 2.0#
| Loại token | Mục đích | Thời hạn |
|---|---|---|
| Access Token | Truy cập tài nguyên (API) | Ngắn (vài phút đến vài giờ) |
| Refresh Token | Làm mới Access Token khi hết hạn | Dài (vài ngày đến vài tháng) |
| ID Token | Xác định người dùng (OpenID Connect) | Ngắn |
Access Token chính là Bearer Token trong hầu hết các triển khai OAuth 2.0.
Ví dụ luồng Authorization Code Grant (OAuth 2.0)#
Đây là flow phổ biến nhất, áp dụng cho web app có backend:
Người dùng -> "Đăng nhập bằng Google"
|
v
1. Redirect đến Authorization Server (Google)
|
v
2. Người dùng đồng ý cấp quyền
|
v
3. Authorization Server trả về Authorization Code
|
v
4. Backend đổi Authorization Code lấy Bearer Token
POST /oauth/token
{
"code": "xyz",
"client_id": "...",
"client_secret": "..."
}
|
v
5. Backend nhận Bearer Token
{
"access_token": "eyJhbG...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "abc123..."
}
|
v
6. Backend dùng Bearer Token để gọi API thay mặt người dùng
GET /api/userinfo
Authorization: Bearer eyJhbG...
Bảo mật Bearer Token#
Tại sao gọi là “Bearer”?#
Như đã đề cập, “Bearer” nghĩa là “người cầm” hay “người mang”. Đây vừa là đặc điểm, vừa là rủi ro lớn nhất của cơ chế này:
Ai cầm token, người đó có quyền.
Không có cơ chế built-in nào để xác minh rằng người gửi token chính là chủ sở hữu hợp pháp của nó. Nếu kẻ tấn công đánh cắp được token, chúng có thể giả mạo người dùng mà không cần biết password.
Các mối đe dọa chính#
1. Token bị đánh cắp qua man-in-the-middle (MITM)#
Nếu kết nối không được mã hóa, kẻ tấn công có thể chặn request và đánh cắp token.
Phòng chống: Luôn sử dụng HTTPS (TLS 1.2+).
2. Token bị lộ qua URL (query string)#
Bearer Token có thể được gửi qua query string:
GET /api/data?access_token=eyJhbG...
Điều này cực kỳ nguy hiểm vì URL bị lưu trong:
- Browser history.
- Server logs.
- Referrer headers.
Phòng chống: Không bao giờ gửi Bearer Token qua query string. Luôn dùng HTTP header.
3. Token bị lưu không an toàn trên client#
Nếu token được lưu trong localStorage, nó có thể bị đánh cắp qua XSS (Cross-Site Scripting).
Phòng chống:
- Lưu token trong HttpOnly cookie (không thể truy cập từ JavaScript).
- Hoặc lưu trong memory (biến JavaScript) — token mất khi refresh trang nhưng an toàn hơn.
- Triển khai Content Security Policy (CSP) để giảm thiểu XSS.
4. Token không có thời hạn hoặc thời hạn quá dài#
Token không hết hạn là một quả bom nổ chậm: nếu bị đánh cắp một lần, kẻ tấn công có quyền truy cập vĩnh viễn.
Phòng chống:
- Access Token nên có thời hạn ngắn (15-60 phút).
- Sử dụng Refresh Token để lấy Access Token mới.
- Triển khai cơ chế revoke token.
Best Practices tổng hợp#
- Luôn dùng HTTPS — không có ngoại lệ.
- Gửi token trong HTTP Header — không phải query string hay cookie.
- Đặt thời hạn ngắn cho Access Token — lý tưởng 15-30 phút.
- Sử dụng Refresh Token rotation — mỗi lần refresh, cấp một Refresh Token mới.
- Lưu token an toàn trên client — HttpOnly cookie cho web, Keychain/Keystore cho mobile.
- Validate token ở mọi request — kiểm tra chữ ký, thời hạn, scopes.
- Triển khai token revocation — khả năng thu hồi token khi cần (logout, đổi mật khẩu, phát hiện xâm phạm).
- Không nhúng token trong source code — sử dụng biến môi trường hoặc secret manager.
- Áp dụng rate limiting — ngăn chặn brute-force token.
- Ghi log mọi lần xác thực thất bại — phục vụ audit và phát hiện tấn công.
So sánh Bearer Token với các phương thức xác thực khác#
Bearer Token vs Basic Authentication#
| Tiêu chí | Bearer Token | Basic Auth |
|---|---|---|
| Cách hoạt động | Token được cấp sau login | Gửi username/password mỗi request |
| Hết hạn | Có thể hết hạn và refresh | Không có cơ chế hết hạn |
| Bảo mật | Password không lộ mỗi request | Password gửi đi liên tục |
| Phân quyền | Hỗ trợ scopes, claims | Không có |
| Revoke | Có thể thu hồi token | Phải đổi password |
| Phù hợp | Single Page App, Mobile, API | Hệ thống legacy, internal tools |
Bearer Token vs API Key#
| Tiêu chí | Bearer Token | API Key |
|---|---|---|
| Mục đích chính | Xác thực người dùng | Xác thực ứng dụng |
| Vòng đời | Ngắn (có refresh) | Dài (thường không đổi) |
| Phân quyền | Scopes chi tiết | Thường là all-or-nothing |
| Tiêu chuẩn | RFC 6750 (OAuth 2.0) | Không có chuẩn chính thức |
| Ví dụ | Authorization: Bearer eyJ... |
X-API-Key: sk_live_abc123 |
Bearer Token vs Session Cookie#
| Tiêu chí | Bearer Token | Session Cookie |
|---|---|---|
| Lưu trữ state | Stateless (token tự chứa thông tin) | Stateful (server lưu session) |
| Domain | Mọi domain (CORS) | Một domain |
| Mobile app | Tốt | Khó (không có cookie) |
| CSRF | Không bị ảnh hưởng | Dễ bị CSRF |
| XSS | Dễ bị nếu lưu trong localStorage | An toàn hơn nếu dùng HttpOnly |
Xu hướng hiện đại: sử dụng kết hợp cả hai — Bearer Token cho mobile app và third-party API, Session Cookie (với HttpOnly flag) cho web app truyền thống.
Triển khai Bearer Authentication#
Backend (Node.js + Express)#
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
// Middleware xác thực Bearer Token
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1]; // "Bearer TOKEN"
if (!token) {
return res.status(401).json({ error: 'Missing Bearer Token' });
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
// Phân biệt lỗi hết hạn và lỗi khác
if (err.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Token expired' });
}
return res.status(403).json({ error: 'Invalid token' });
}
req.user = user; // Gắn thông tin user vào request
next();
});
}
// Route được bảo vệ
app.get('/api/profile', authenticateToken, (req, res) => {
res.json({
userId: req.user.sub,
name: req.user.name,
message: 'Đây là dữ liệu được bảo vệ'
});
});
Frontend (JavaScript)#
class ApiClient {
constructor() {
this.accessToken = null;
}
async login(username, password) {
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
const data = await response.json();
this.accessToken = data.access_token;
return data;
}
async request(path, options = {}) {
const headers = {
'Content-Type': 'application/json',
...options.headers
};
// Tự động đính kèm Bearer Token
if (this.accessToken) {
headers['Authorization'] = `Bearer ${this.accessToken}`;
}
const response = await fetch(`https://api.example.com${path}`, {
...options,
headers
});
// Tự động xử lý 401
if (response.status === 401) {
// Thử refresh token hoặc redirect đến login
throw new Error('Unauthorized - Token expired or invalid');
}
return response.json();
}
}
// Sử dụng
const api = new ApiClient();
await api.login('user@example.com', 'password123');
const profile = await api.request('/api/profile');
Backend với nhiều scopes#
// Middleware kiểm tra scope
function requireScope(...requiredScopes) {
return (req, res, next) => {
const tokenScopes = req.user.scope ? req.user.scope.split(' ') : [];
const hasAllScopes = requiredScopes.every(
scope => tokenScopes.includes(scope)
);
if (!hasAllScopes) {
return res.status(403).json({
error: 'Insufficient permissions',
required: requiredScopes,
granted: tokenScopes
});
}
next();
};
}
// Sử dụng
app.get('/api/admin/users', authenticateToken, requireScope('admin:read'), (req, res) => {
// Chỉ user có scope "admin:read" mới vào được
});
app.delete('/api/admin/users/:id', authenticateToken, requireScope('admin:write'), (req, res) => {
// Chỉ user có scope "admin:write" mới vào được
});
Bearer Token trong các giao thức và nền tảng#
MCP (Model Context Protocol)#
Trong MCP — giao thức kết nối AI models với external tools — Bearer Token thường được sử dụng để xác thực SSE transport. Ví dụ cấu hình file .mcp.json:
{
"mcpServers": {
"vnCms": {
"type": "sse",
"url": "https://cms.example.com/mcp/sse",
"headers": {
"Authorization": "Bearer eyJhbGc...",
"X-MCP-Key": "mcp_key_abc123"
}
}
}
}
GitHub Personal Access Token#
GitHub sử dụng Bearer Token (Personal Access Token) để xác thực API:
curl -H "Authorization: Bearer ghp_abc123def456" \
https://api.github.com/user/repos
Docker Registry#
Docker Registry xác thực bằng Bearer Token theo chuẩn OAuth 2.0:
GET /v2/library/nginx/manifests/latest
Authorization: Bearer eyJhbG...
Câu hỏi thường gặp (FAQ)#
1. Bearer Token có phải là JWT không?#
Không. Bearer Token là phương thức xác thực (cách gửi token), JWT là định dạng token. Bạn có thể dùng JWT làm Bearer Token, hoặc dùng các định dạng khác như opaque token. Miễn là token được gửi qua header Authorization: Bearer <token>, nó là Bearer Token.
2. Làm sao để revoke một Bearer Token?#
Tùy vào loại token:
- JWT: Duy trì một blacklist (danh sách token bị thu hồi) trên server. Mỗi request kiểm tra token có trong blacklist không.
- Opaque Token: Xóa token khỏi database. Các request sau sẽ thất bại khi introspection.
- Cách khác: Giảm thời hạn token xuống rất ngắn (5-15 phút) và dùng Refresh Token rotation.
3. Nên lưu Bearer Token ở đâu trên client?#
Không có câu trả lời tuyệt đối, mỗi cách có trade-off:
| Vị trí | Ưu điểm | Nhược điểm |
|---|---|---|
| HttpOnly Cookie | Chống XSS tốt | Dễ bị CSRF, cần cấu hình SameSite |
| localStorage | Đơn giản, không mất khi refresh | Dễ bị XSS đánh cắp |
| Memory (biến JS) | An toàn nhất | Mất khi refresh, phải login lại |
| Keychain/Keystore | An toàn nhất cho mobile | Chỉ dành cho native app |
4. Bearer Token có cần mã hóa không?#
Không bắt buộc mã hóa payload, nhưng bắt buộc ký (sign) token. Chữ ký đảm bảo token không bị chỉnh sửa. Nếu payload chứa thông tin nhạy cảm, bạn nên mã hóa thêm (JWE — JSON Web Encryption).
Kết luận#
Bearer Token là một trong những cơ chế xác thực quan trọng nhất trong hệ sinh thái API hiện đại. Sự đơn giản của nó — chỉ cần một header — kết hợp với tính linh hoạt trong việc hỗ trợ JWT, OAuth 2.0, và vô số nền tảng khác — đã khiến nó trở thành lựa chọn mặc định cho hầu hết các hệ thống xác thực ngày nay.
Tuy nhiên, sức mạnh đi kèm với trách nhiệm. Cái tên “Bearer” vừa là đặc điểm, vừa là lời cảnh báo: bất kỳ ai cầm token đều có quyền. Vì vậy, việc bảo vệ token — qua HTTPS, thời hạn ngắn, lưu trữ an toàn, và cơ chế revoke — là điều không thể xem nhẹ.
Nếu bạn đang xây dựng một API, một ứng dụng di động, hay một hệ thống microservices, hiểu và triển khai Bearer Authentication đúng cách là một trong những kỹ năng nền tảng bạn cần nắm vững.
Bài viết được cập nhật lần cuối vào tháng 5 năm 2026. Các thông tin về Bearer Token và bảo mật API có thể thay đổi theo thời gian và tiêu chuẩn mới.