logo
GeekFormat
Encoded Token172 charsCập nhật 2026-07
header
payload
signature
Valid JWTHS256
Secret38 chars
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022
}
Claims details4 items
sub· Chủ thể1234567890
name· NameJohn Doe
admin· Admintrue
iat· Thời điểm phát hành151623902209:30:22 18/01/2018
Header details2 items
algHS256HMAC (đối xứng)
typ· TypeJWT
All operations run locally in your browser; the Token and key are never sent to any server.

Công cụ JWT trực tuyến miễn phí, hỗ trợ giải mã, xác minh và tạo JWT Token, xem Header, Payload và thông tin chữ ký, phù hợp gỡ lỗi xác thực API.

Đề xuất Liên quan

Trường hợp sử dụng

  • Giải mã JWT trực tuyến: tách nhanh token trong khi gỡ lỗi đăng nhập OAuth 2.0 / OIDC để kiểm tra thuật toán Header và Claims Payload
  • Xác minh chữ ký JWT: sử dụng Secret / khóa công khai để xác minh chữ ký token theo thời gian thực và quyết định xem 401 là 'chữ ký xấu', 'đã hết hạn' hay 'thuật toán không khớp'
  • Tạo JWT kiểm tra trong khi tích hợp: phát hành JWT trong trình duyệt với cặp khóa kiểm tra, không cần backend tạm thời thay đổi mã để phát hành token
  • Chuyển đổi PEM ↔ JWK: OIDC IdP cho bạn JWK nhưng máy chủ cần PEM (hoặc ngược lại) — chuyển đổi tại chỗ thay vì viết script OpenSSL
  • Chẩn đoán 401 Unauthorized: kiểm tra từng bước thời hạn hết hạn, khớp alg với cổng, khớp khóa và định dạng PEM
  • So sánh RS256 và PS256: nhiều nhà cung cấp OIDC mặc định sử dụng RS256 trong khi AWS SigV4 ưu tiên PS256 — chuyển đổi thuật toán với cùng cặp khóa RSA và so sánh kết quả
  • Học cơ chế nội bộ JWT: thay đổi alg, sửa Payload, đổi khóa trong trình duyệt và xem chữ ký bị phá vỡ theo thời gian thực — nhanh hơn nhiều so với đọc RFC

Tính năng

  • Giải mã + Xác minh + Tạo trong một nơi: dán token để tách Header/Payload/Signature, đổi thuật toán và khóa để xác minh chữ ký, sửa Claims và ký lại để tạo token mới — bao phủ toàn bộ chuỗi xử lý sự cố JWT
  • Hỗ trợ tất cả 13 thuật toán: HS256/HS384/HS512 (HMAC), RS256/RS384/RS512 (RSA-PKCS1-v1_5), ES256/ES384/ES512 (ECDSA), PS256/PS384/PS512 (RSA-PSS), EdDSA — bao phủ OAuth 2.0, OIDC, JWS, cổng API và SSO doanh nghiệp
  • Định dạng PEM và JWK: khóa RSA, ECDSA và Ed25519 chấp nhận chuỗi PEM (với tiêu đề -----BEGIN PUBLIC KEY-----) và JSON JWK (trường kid/kty/n/e) — chèn trực tiếp đầu ra OIDC /.well-known/jwks.json
  • Nhiều dạng nhập Secret HMAC: chuỗi UTF-8 thô, byte hex hoặc mã hóa Base64/Base64URL — chuyển đổi bằng một cú nhấp chuột, để không bao giờ xảy ra 'trông giống nhau nhưng chữ ký thất bại'
  • Tạo cặp khóa tự động: cặp khóa RSA-2048, RSA-4096, P-256, P-384 và Ed25519 được tạo trong trình duyệt, trình bày ở định dạng PEM và JWK để sử dụng kiểm tra ngay lập tức
  • Tô sáng ngữ nghĩa Claims: exp / iat / nbf tự động chuyển đổi sang thời gian dễ đọc với trạng thái đã hết hạn / chưa hợp lệ / đã phát hành được tô sáng; alg / typ / kid trong Header được dán nhãn riêng
  • 100% phía client, không tải lên: mỗi phân tích, xác minh và ký chạy qua Web Crypto API native của trình duyệt — token, khóa và payload không bao giờ rời khỏi trình duyệt, tuân theo nguyên tắc bảo mật 'không bao giờ dán token production vào công cụ online ngẫu nhiên'
  • Sao chép một cú nhấp chuột: Header, Payload, Signature và token mới tạo có thể sao chép độc lập cho tài liệu, ticket và lệnh curl

Cách Sử dụng

  1. Dán hoặc nhập token: đặt chuỗi JWT vào trường nhập; công cụ tự động tách Header, Payload và Signature và hiển thị mỗi phần dưới dạng JSON được định dạng
  2. Chọn thuật toán: chuyển đổi giữa HS256 / RS256 / ES256 / PS256 / EdDSA; công cụ suy luận từ Header.alg và đánh dấu bất kỳ sự không khớp nào
  3. Nhập khóa: dán Secret HMAC, chuỗi PEM hoặc JSON JWK; đối với thuật toán bất đối xứng, nhấp vào 'Tạo cặp khóa' để nhận khóa kiểm tra ngay lập tức
  4. Xác minh hoặc ký lại: trong chế độ Decode, xác minh bằng khóa công khai và xem '✅ chữ ký hợp lệ / ❌ chữ ký không hợp lệ'; trong chế độ Encode, sửa Claims và ký bằng khóa riêng để tạo token mới

Câu hỏi Thường gặp

Ba phần của JWT là gì?

Chuỗi JWT có dạng `Header.Payload.Signature`, mỗi đoạn được mã hóa Base64URL. Header khai báo thuật toán (như HS256, RS256) và loại token (typ: JWT); Payload mang Claims của người dùng (tuyên bố), các trường phổ biến là sub (ID người dùng), iat (thời gian phát hành), exp (thời gian hết hạn), nbf (not-before), aud (đối tượng), iss (người phát hành); Signature là kết quả của việc ký hai đoạn đầu bằng khóa, mục đích là 'phát hiện giả mạo' không phải 'chống rò rỉ'.

Tôi có thể sửa Payload sau khi giải mã không?

Bạn có thể xem và sửa, nhưng **không thể giả mạo**. Ngay khi bạn thay đổi Header hoặc Payload, Signature ban đầu trở nên không hợp lệ và máy chủ sẽ từ chối xác minh. Để làm cho token đã sửa hợp lệ lại, bạn phải **ký lại** bằng cùng thuật toán và cùng khóa — đó chính xác là lý do công cụ này cung cấp 'giải mã + sửa + tạo' trong một: giải mã để xem, thay đổi và tạo ngay token mới để kiểm tra, để bạn không cần yêu cầu backend tạm thời thay đổi mã để phát hành.

Sự khác biệt giữa HS256, RS256, ES256, PS256 và EdDSA là gì?

HS256 sử dụng HMAC với Secret chia sẻ (đối xứng), nhanh nhưng quản lý secret là quan trọng. RS256 sử dụng khóa riêng/công khai RSA (bất đối xứng), người phát hành ký bằng khóa riêng, người xác minh sử dụng khóa công khai. ES256 sử dụng ECDSA với đường cong elliptic (P-256), chữ ký ngắn hơn. PS256 sử dụng RSA-PSS, an toàn hơn RS256. EdDSA (thường là Ed25519) nhanh và tất định, được khuyến nghị cho OAuth 2.1.

Tại sao JWT của tôi liên tục hiển thị 'Invalid Signature'?

Thường là do khóa, định dạng Secret, thuật toán hoặc mã hóa Base64URL không khớp chính xác. Một khoảng trắng thừa, dòng mới PEM sai hoặc nhầm lẫn giữa Base64 và Base64URL là đủ. Kiểm tra từng byte và xác nhận Header.alg khớp với thuật toán đã chọn.

Cùng một khóa RSA có thể xác minh chéo RS256 và PS256 không?

Không. RS256 sử dụng RSASSA-PKCS1-v1_5, PS256 sử dụng RSA-PSS. Ngay cả với cùng khóa RSA, chúng không thể xác minh chéo. Người ký và người xác minh phải sử dụng cùng thuật toán.

Tấn công alg:none là gì?

Kẻ tấn công thay đổi Header thành `{"alg":"none"}` (không có chữ ký) hoặc thay thế RS256 bằng HS256 (sử dụng khóa công khai như thể nó là Secret HMAC). Máy chủ phải áp dụng danh sách cho phép thuật toán và không bao giờ cho phép token quyết định sử dụng thuật toán nào.

Tôi chuyển đổi giữa PEM và JWK như thế nào?

PEM là ký hiệu OpenSSL cổ điển với dòng BEGIN/END. JWK là JSON và phổ biến trong OAuth/OIDC. Các nhà cung cấp OIDC thường xuất bản khóa công khai qua `/.well-known/jwks.json`. Công cụ này có thể xử lý trực tiếp định dạng PEM và JWK.

Trình duyệt có thể xác minh chữ ký JWT trực tiếp không?

Có. Web Crypto API native của trình duyệt (`window.crypto.subtle`) hỗ trợ ký và xác minh HMAC, RSA, ECDSA, RSA-PSS và Ed25519, không cần thư viện bên thứ ba. Công cụ này sử dụng `crypto.subtle.importKey` và `crypto.subtle.verify` ở front-end cho mỗi xác minh, vì vậy không bao giờ gửi token hoặc khóa của bạn. Lưu ý: Web Crypto chỉ khả dụng trong ngữ cảnh bảo mật: **HTTPS** hoặc `localhost`.

Token của tôi có được gửi đến máy chủ không?

Không. Toàn bộ phân tích, xác minh và ký trong công cụ này chạy trong trình duyệt qua Web Crypto API native. Token, Header, Payload, Signature, secret / khóa riêng và bất kỳ cặp khóa nào được tạo không bao giờ được gửi đến máy chủ. Mở tab Network của DevTools trình duyệt và bạn sẽ không thấy bất kỳ yêu cầu đi nào mang nội dung token. Trang có thể được sử dụng ngoại tuyến sau khi tải.

JWT có phải là nơi an toàn cho thông tin người dùng nhạy cảm không?

**Không.** Payload JWT theo mặc định là văn bản thuần — bất kỳ ai có token đều có thể giải mã Base64URL và đọc nội dung. Không có mã hóa. **Không bao giờ đặt** mật khẩu, số CMND/CCCD, số thẻ tín dụng, khóa API, access token hoặc refresh token dưới dạng văn bản thuần trong JWT. Nếu bạn cần mã hóa, sử dụng JWE (RFC 7516) thay vì JWS. JWT phù hợp cho Claims không nhạy cảm (ID người dùng, vai trò, thời gian hết hạn, ID người thuê); dữ liệu nhạy cảm nên được truy vấn ở phía máy chủ bằng cách sử dụng `sub`.

Giải mã, Xác minh và Tạo JWT là gì?

JWT (JSON Web Token) là một tiêu chuẩn mở được IETF định nghĩa trong RFC 7519 (RFC 7515 mô tả dạng chữ ký JWS, RFC 7516 mô tả mã hóa JWE, RFC 7517 định nghĩa khóa JWK) để truyền an toàn thông tin người dùng 'đã khai báo' giữa các yêu cầu HTTP, luồng OIDC và cuộc gọi vi dịch vụ. Một chuỗi JWT tiêu chuẩn bao gồm ba đoạn được mã hóa Base64URL: Header (thuật toán và loại), Payload (Claims, dữ liệu người dùng) và Signature (chữ ký dựa trên khóa trên hai đoạn đầu). Ba đoạn được nối bằng dấu chấm `.`, ví dụ `eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`.

**JWT không phải là mã hóa.** Đây là hiểu lầm phổ biến nhất. Payload theo mặc định là văn bản thuần — bất kỳ ai cũng có thể giải mã Base64URL và đọc nội dung. JWT cung cấp **phát hiện giả mạo**, không phải bảo mật: máy chủ ký lại Header.Payload bằng khóa chia sẻ và so sánh với Signature của token. Nếu khớp, token không bị thay đổi trong quá trình truyền. Đây là phép ẩn dụ 'vé tàu có dấu chống giả': thanh tra quan tâm vé có thật không, không phải mã QR có đọc được không.

JWT phân chia trách nhiệm rõ ràng giữa 13 thuật toán. **Họ HMAC** (HS256/HS384/HS512) sử dụng khóa đối xứng để ký và xác minh, nhanh và đơn giản, phù hợp với một dịch vụ hoặc cụm đáng tin cậy; secret phải có ít nhất độ dài digest (ví dụ: ≥ 32 byte cho HS256). **Họ RSA** (RS256/RS384/RS512) sử dụng RSASSA-PKCS1-v1_5, lược đồ bất đối xứng phổ biến nhất — người ký có khóa riêng, người xác minh có khóa công khai. **Họ RSA-PSS** (PS256/PS384/PS512) sử dụng padding RSA-PSS mới hơn với đảm bảo bảo mật mạnh hơn, được AWS SigV4 và các nhà cung cấp danh tính OIDC hiện đại ưu tiên. **Họ ECDSA** (ES256/ES384/ES512) sử dụng đường cong elliptic (P-256/P-384/P-521 tương ứng) với chữ ký ngắn hơn và hiệu suất tốt hơn. **EdDSA** (chủ yếu là Ed25519) cực kỳ nhanh và tất định (cùng thông điệp + cùng khóa = cùng chữ ký mỗi lần) và là thuật toán được khuyến nghị trong OAuth 2.1 và các giao thức mới.

Bảo mật là nơi JWT vấp ngã trong production. OWASP JWT Cheat Sheet liệt kê ít nhất bốn quy tắc cứng: (1) không bao giờ đặt mật khẩu, giấy tờ tùy thân quốc gia, số thẻ hoặc khóa API dưới dạng văn bản thuần trong Payload; (2) máy chủ phải **không bao giờ tin tưởng trường alg** được khai báo trong Header của Token — phải xác minh bằng thuật toán được mã hóa cứng, nếu không kẻ tấn công viết lại tiêu đề thành `alg: none` sẽ vượt qua tất cả (đây là nguồn gốc của các CVE lịch sử như CVE-2015-9235); (3) secret HMAC phải ngẫu nhiên và có ít nhất 32 byte, không bao giờ là chuỗi ngắn; (4) xác minh không chỉ là kiểm tra chữ ký — bạn cũng phải xác thực `exp` (hết hạn), `nbf` (not-before), `iss` (người phát hành) và `aud` (đối tượng). Công cụ này tô sáng từng Claims này trong UI để bạn có thể nói ngay lập tức sự cố là vấn đề chữ ký, vấn đề thời gian hay vấn đề Claims.

JWT không thay thế phiên. Phiên lưu trữ trạng thái người dùng trên máy chủ (Redis hoặc cơ sở dữ liệu); JWT đóng gói trạng thái vào token. Kiến trúc vi dịch vụ, API không trạng thái, ứng dụng khách di động và cấu hình có nhiều CORS được hưởng lợi từ JWT; hệ thống doanh nghiệp truyền thống và luồng yêu cầu thu hồi ngay lập tức (ví dụ: 'đá người dùng này ngay bây giờ') vẫn được phục vụ tốt hơn bởi phiên. Công cụ này bao gồm cả gỡ lỗi JWT thuần túy và các bước phân tích Token / xác minh chữ ký / sửa Payload của việc di chuyển từ phiên sang JWT.

Code Examples

50 lines of Node.js: hand-written HS256 sign and verify

javascript

Distills JWT's core mechanism: encode Header and Payload in Base64URL, then HMAC-SHA256 the `header.payload` string. In production, use a library like jsonwebtoken or jose — this snippet exists to make signature failures debuggable.

const crypto = require('node:crypto')

function b64url(input) {
  return Buffer.from(input)
    .toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '')
}

function hmacSign(data, secret) {
  return b64url(crypto.createHmac('sha256', secret).update(data).digest())
}

function sign(payload, secret) {
  const header = b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
  const body = b64url(JSON.stringify(payload))
  const signature = hmacSign(`${header}.${body}`, secret)
  return `${header}.${body}.${signature}`
}

function verify(token, secret) {
  const [h, p, s] = token.split('.')
  const expected = hmacSign(`${h}.${p}`, secret)
  const a = Buffer.from(s)
  const b = Buffer.from(expected)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

const SECRET = 'my-super-secret-key'
const payload = { userId: 42, role: 'admin', exp: Math.floor(Date.now() / 1000) + 3600 }
const token = sign(payload, SECRET)

console.log(token)
console.log(verify(token, SECRET))       // true
console.log(verify(token, 'wrong-key'))  // false

Browser-side: Web Crypto API for HMAC signing

html

The core idea of this tool's front-end: use the browser's native crypto.subtle for HMAC, RSA, ECDSA, RSA-PSS and Ed25519 verification — no third-party library needed. Drop this into any HTML page to mint HS256 tokens.

<!doctype html>
<html>
  <body>
    <pre id="out"></pre>
    <script>
      const out = document.getElementById('out')

      const b64url = buf =>
        btoa(String.fromCharCode(...new Uint8Array(buf)))
          .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

      const b64urlStr = str => b64url(new TextEncoder().encode(str))

      async function sign(payload, secret) {
        const header = b64urlStr(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
        const body = b64urlStr(JSON.stringify(payload))
        const data = new TextEncoder().encode(`${header}.${body}`)

        const key = await crypto.subtle.importKey(
          'raw',
          new TextEncoder().encode(secret),
          { name: 'HMAC', hash: 'SHA-256' },
          false,
          ['sign']
        )

        const sig = await crypto.subtle.sign('HMAC', key, data)
        return `${header}.${body}.${b64url(sig)}`
      }

      ;(async () => {
        const token = await sign({ user: 'alice', role: 'admin' }, 'browser-demo-secret')
        out.textContent = token
      })()
    </script>
  </body>
</html>

Node.js: verify RS256 with jose (the right way)

javascript

Use a mature library like jose, jsonwebtoken, or PyJWT in production — never roll your own. This snippet shows how jose verifies an RS256 token, prints the failure reason on error (alg mismatch, bad signature, expired, kid not found, etc).

import { jwtVerify, importSPKI } from 'jose'
import { readFile } from 'node:fs/promises'

const token = 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.payload.signature'
const publicKeyPem = await readFile('public.pem', 'utf8')

try {
  const { payload, protectedHeader } = await jwtVerify(
    token,
    await importSPKI(publicKeyPem, 'RS256'),
    {
      issuer: 'https://idp.example.com',
      audience: 'my-app',
      algorithms: ['RS256'],     // critical: algorithm whitelist blocks alg:none and HS256-substitution attacks
    }
  )
  console.log('alg =', protectedHeader.alg)
  console.log('sub  =', payload.sub)
} catch (err) {
  console.error('verify failed:', err.code, err.message)
  // common: ERR_JWT_EXPIRED / ERR_JWS_INVALID / ERR_JWS_SIGNATURE_VERIFICATION_FAILED
}

Python: parse a token and print its Claims with PyJWT

python

The most common way to debug JWT on the Python side. PyJWT's decode() validates exp / nbf / iat by default and returns the result as a plain dict.

import jwt

token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxw'

# Parse (no signature check, just look at Header and Payload)
print(jwt.get_unverified_header(token))
# {'alg': 'HS256', 'typ': 'JWT'}

print(jwt.decode(token, options={'verify_signature': False}))
# {'sub': '1234'}

# Full verification
claims = jwt.decode(
    token,
    'my-super-secret-key',
    algorithms=['HS256'],
    audience='my-app',
    issuer='my-service',
)
print(claims['sub'])

Supported Video Formats

FormatMIMEBrowser supportWhen to use
HS256 / HS384 / HS512HMAC + SHA-256/384/512UniversalThuật toán khóa đối xứng: cùng một Secret dùng để ký và xác minh. Cách này đơn giản, nhanh, phù hợp với cụm dịch vụ nằm trong ranh giới tin cậy. Secret nên dài tối thiểu 32 byte cho HS256, 48 byte cho HS384 và 64 byte cho HS512.
RS256 / RS384 / RS512RSASSA-PKCS1-v1_5 + SHA-2Web Crypto APIThuật toán bất đối xứng phổ biến nhất. Ký bằng private key, xác minh bằng public key. Đây thường là lựa chọn mặc định của nhiều nhà cung cấp OIDC, API gateway và hệ thống SSO doanh nghiệp.
PS256 / PS384 / PS512RSA-PSS + SHA-2Web Crypto APIRSA-PSS là lựa chọn thay thế mới hơn và an toàn hơn cho RS256. AWS SigV4, AWS Cognito và các nhà cung cấp OIDC hiện đại thường ưu tiên nó. Cần đặt saltLength rõ ràng để kết quả xác minh khớp.
ES256 / ES384 / ES512ECDSA + P-256/P-384/P-521Web Crypto APIChữ ký dựa trên đường cong elliptic. Chữ ký ngắn (ES256 chỉ 64 byte), hiệu năng tốt và giúp JWT nhỏ hơn. Sign in with Apple mặc định dùng ES256.
EdDSA (Ed25519)Ed25519 / Ed448Web Crypto APIThuật toán chữ ký thế hệ mới, hiệu năng cao. Chữ ký có tính tất định (cùng thông điệp + cùng khóa = cùng chữ ký), không gặp rủi ro tái sử dụng nonce và rất phù hợp cho các giao thức mới.

Output Example

A real MP3 file encoded to a Data URI — copy-ready:

Header (Base64URL): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload (Base64URL): eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzE2MjM5MDIyfQ
Signature: kZJfaYjK3iCkVFL5EL9zGRZ5SmD8_x2h6B5c7pVFfVGo

Privacy & Security

Bàn làm việc JWT này chạy 100% trong trình duyệt của bạn, được hỗ trợ bởi Web Crypto API native của trình duyệt. Token bạn dán, Header, Payload, Signature, Secret HMAC, bất kỳ khóa riêng RSA/ECDSA nào, bất kỳ cặp khóa nào được tạo và mỗi tính toán chữ ký/xác minh đều ở trên thiết bị của bạn — chúng không bao giờ đi đến máy chủ, không bao giờ được ghi log, không bao giờ được phân tích và không bao giờ được lưu cache. Trang có thể được sử dụng ngoại tuyến sau khi tải. Thực tiễn tốt nhất: không bao giờ dán token production tồn tại lâu dài hoặc khóa riêng production vào bất kỳ công cụ online nào, bao gồm cả công cụ này. Công cụ này phù hợp để gỡ lỗi, kiểm tra tích hợp, học tập và tạo token kiểm tra — secret production và khóa riêng nên được xử lý trong môi trường được kiểm soát, cục bộ.

Authoritative References

Troubleshooting

Invalid Signature: 'signature is invalid'

Token và khóa xác minh không khớp. Nguyên nhân thông thường: (1) khóa của máy chủ và khóa bạn dán vào công cụ khác nhau (phổ biến nhất); (2) khóa chứa ký tự vô hình (khoảng trắng cuối, dòng mới, ký tự có độ rộng bằng không); (3) Base64 và Base64URL bị nhầm lẫn; (4) thuật toán sai được chọn (Header nói HS256, máy chủ xác minh là RS256 hoặc ngược lại). Đầu tiên kiểm tra khóa có khớp từng byte không: chú ý đến dòng mới cuối của PEM, khoảng trắng cuối của Secret HMAC và giá trị `k` JWK có thể đã được giải mã URL sai. Xác nhận thuật toán trong công cụ khớp với Header.alg của token. Sử dụng decode-plus-verify của công cụ này để tái tạo lỗi chính xác và xác nhận nó xảy ra giữa 'giải mã thành công' và 'xác minh thất bại'.

HTTP 401 Unauthorized: Token Expired hoặc iat trong tương lai

Xác minh chữ ký đã qua nhưng `exp` ở quá khứ (Token Expired), `nbf` vẫn ở tương lai (Not Before) hoặc `iat` sau thời gian hiện tại của máy chủ (thường do lệch đồng hồ). Trường hợp phổ biến khác là `aud` (đối tượng) không khớp: token được phát hành cho Ứng dụng A nhưng được xác minh bởi Ứng dụng B. Sử dụng khu vực Claims được tô sáng trong công cụ này để xem trạng thái exp / nbf / iat ngay lập tức. exp đỏ = đã hết hạn, phát hành lại. nbf đỏ = chưa hợp lệ, kiểm tra xem iat có phải là thời gian tương lai không. aud đỏ = đối tượng sai, kiểm tra xem máy chủ có được cấu hình đúng đối tượng không.

Lỗi nhập PEM hoặc JWK

PEM có dòng trống thừa hoặc thiếu đánh dấu tiêu đề/chân (`-----BEGIN PUBLIC KEY-----`); JWK thiếu trường bắt buộc (`kty` / `n` / `e` / `kid`); giá trị `k` JWK thiếu padding Base64URL (phải được đệm bằng `=` hoặc nghiêm ngặt không có `=`); khóa riêng RSA được nhập làm khóa công khai; khóa riêng Ed25519 (hạt giống 32 byte) được cung cấp dưới dạng 64 byte. Xuất lại PEM PKIX tiêu chuẩn bằng `openssl rsa -in key.pem -pubout -outform PEM` hoặc `openssl ec -in key.pem -pubout`; đối với JWK, sử dụng đầu ra thô từ điểm cuối OIDC Discovery `/.well-known/jwks.json` thay vì mã hóa thủ công. Công cụ này tự động phát hiện tiêu đề PEM, padding thiếu và trường JWK thiếu và đưa ra gợi ý.

RS256 và PS256 lỗi chữ ký giữa các ngôn ngữ

RS256 sử dụng RSASSA-PKCS1-v1_5, PS256 sử dụng RSA-PSS. Hai cái này **không thể xác minh chéo** — token được ký RS256 bằng một khóa RSA cụ thể sẽ luôn thất bại xác minh PS256, và chữ ký có thể khác nhau vài byte về độ dài. Đảm bảo người ký và người xác minh sử dụng cùng thuật toán. AWS SigV4 sử dụng PS256, hầu hết OIDC IdP sử dụng RS256. RSA-PSS cũng có tham số `saltLength` — OpenSSL mặc định 32, jose mặc định 32, `rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}` của Go là tương đương chính xác. Cố định điều này trước khi kiểm tra tích hợp giữa các ngôn ngữ.

Tấn công alg:none và tấn công thay thế khóa HS256

Máy chủ chọn thuật toán xác minh dựa trên alg được khai báo trong Header của token. Kẻ tấn công viết lại tiêu đề thành `alg: none` (không có chữ ký) hoặc viết lại token RS256 thành HS256 (sử dụng khóa công khai như thể nó là Secret HMAC chia sẻ) và vượt qua xác minh. Các CVE lịch sử như CVE-2015-9235 (jsonwebtoken) và CVE-2022-23529 (nhiều thư viện Node) bắt nguồn từ mẫu này. Máy chủ phải áp dụng danh sách cho phép thuật toán — ví dụ `algorithms: ['RS256']` — và không bao giờ cho phép token quyết định sử dụng thuật toán nào. UI của công cụ này hiển thị cả Header.alg và thuật toán bạn thực sự đã chọn, và đánh dấu sự không khớp: đây là bản demo trực tiếp 'ứng dụng khách không nên tin tưởng Header.alg'.