Chuẩn rồi, JWT::encode / JWT::decodebằng HMAC hoặc RSA/ECDSA, tuỳ algorithm (alg) bạn chọn 👇
Nhưng mặc định & phổ biến nhất là HMAC (HS256).


1️⃣ JWT ký kiểu gì?

JWT có 3 nhóm thuật toán chính:

🔹 1. HMAC (đối xứng – shared secret)

HS256 / HS384 / HS512
  • Dùng 1 secret key
  • Encode & decode chung một key
  • Nhanh, đơn giản
  • Phổ biến nhất trong PHP / API nội bộ

👉 JWT::encode(..., $secret, 'HS256')
👉 JWT::decode(..., new Key($secret, 'HS256'))

✔️ Cái này chính xác là HMAC


🔹 2. RSA (bất đối xứng – public/private key)

RS256 / RS384 / RS512
  • Ký bằng private key
  • Verify bằng public key
  • Phù hợp SSO, OAuth, nhiều service verify

👉 Auth Server ký
👉 Các service khác chỉ cần public key


🔹 3. ECDSA (elliptic curve – gọn & nhanh)

ES256 / ES384 / ES512
  • Nhẹ, chữ ký ngắn
  • Dùng trong hệ lớn, mobile

2️⃣ Với PHP (firebase/php-jwt) – ví dụ thực tế

✅ HMAC (HS256 – phổ biến nhất)

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$payload = [
    'iss' => 'example.com',
    'sub' => 123,
    'iat' => time(),
    'exp' => time() + 3600
];
$secret = 'super-secret-key';
$jwt = JWT::encode($payload, $secret, 'HS256');
$decoded = JWT::decode($jwt, new Key($secret, 'HS256'));

👉 Encode = hash_hmac() bên trong
👉 Decode = verify lại HMAC


❗ HMAC có nhược điểm gì?

  • Ai có secret là vừa ký vừa verify
  • Không phù hợp:
    • nhiều service
    • public verify
    • zero-trust

👉 Nếu bạn:

  • VPS → máy local
  • API nội bộ
  • 1 backend

➡️ HS256 là chuẩn bài


3️⃣ Khi nào KHÔNG nên dùng HMAC?

Trường hợpNên dùng
SSO nhiều hệRS256
Public verifyRS256
Microservice lớnRS256 / ES256
App nhỏ / cá nhânHS256

4️⃣ Lỗi kinh điển cần tránh ⚠️

❌ Cho client biết secret
❌ Cho phép alg=none
❌ Decode mà không verify alg
❌ Dùng secret quá ngắn

✅ Secret ≥ 32 bytes

bin2hex(random_bytes(32))

5️⃣ Tóm gọn 1 câu cho dễ nhớ

JWT::encode / decode ký bằng HMAC nếu dùng HS256,
còn RSA/ECDSA nếu dùng RS256 / ES256.