Khác biệt cốt lõi: API key định danh ứng dụng/khách hàng và sống rất lâu; access token chứng minh một quyền đã được cấp và hết hạn nhanh.
| API key | Access token | |
|---|---|---|
| Tuổi thọ | Nhiều tháng/năm, đến khi thu hồi tay | Vài phút tới vài giờ |
| Nội dung | Chuỗi ngẫu nhiên, không tự mang thông tin | Có claim (sub, scope, exp) |
| Thu hồi | Xóa/khóa hàng trong DB, có hiệu lực ngay | Chờ hết hạn, trừ khi kiểm phía server |
| Hợp cho | Tích hợp máy-với-máy, webhook, khách hàng B2B | Phiên user, ủy quyền theo scope |
Chọn API key khi bên gọi là hệ thống của đối tác cần thứ đơn giản, dán vào config là chạy. Chọn token khi cần ngữ cảnh user, scope chi tiết, hoặc muốn giới hạn thời gian.
Lưu trong DB: đối xử như mật khẩu — chỉ lưu hash, hiển thị giá trị thô đúng một lần lúc tạo.
create table api_keys (
id uuid primary key,
prefix text not null, -- e.g. 'sk_live_4f2a', shown in UI, indexed
key_hash text not null, -- SHA-256 of the full key
user_id uuid not null,
scopes text[] not null default '{}',
last_used_at timestamptz,
revoked_at timestamptz
);Key ngẫu nhiên đủ dài (≥32 byte) nên SHA-256 là đủ — không cần bcrypt/argon2 như mật khẩu người dùng, vì không có gì để đoán và hash chậm sẽ làm nghẽn mỗi request.
Kèm theo: đặt prefix nhận diện được (sk_live_) để quét rò rỉ trên GitHub, ghi last_used_at để dọn key chết, và luôn gắn rate limit theo key.