Debugging JWT Authentication: A Practical Guide
JWT Anatomy
A JSON Web Token has three dot-separated Base64URL-encoded sections:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
header payload signature
Decoding the header and payload is trivial — they're just Base64. The signature is what provides integrity. Always verify the signature before trusting any claim.
The Most Common JWT Bugs
1. alg: none Acceptance
A token with "alg": "none" and no signature is trivially forgeable. Any library
that accepts it is misconfigured. The Dev Toolkit decode endpoint always reports
the algorithm and flags none explicitly.
2. Wrong Key Type
RS256 tokens require the public key for verification. Passing the private key or a symmetric secret causes a silent failure in some libraries.
3. Expired Tokens
Check the exp claim before trusting a token. The API decodes and displays
exp as a human-readable timestamp alongside the raw Unix epoch.
4. Missing aud Validation
A token signed by a trusted issuer but intended for a different service should
be rejected. Always validate aud (audience) in addition to iss.
Using the API to Debug Tokens
curl -X POST https://api.toolkitapi.io/v1/devtools/jwt-decode \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"token": "eyJ..."}'
Response:
{
"header": { "alg": "HS256", "typ": "JWT" },
"payload": {
"sub": "user_123",
"iat": 1716000000,
"exp": 1716003600,
"exp_human": "2026-05-18 10:00:00 UTC",
"expired": false
},
"signature_present": true
}
Verifying a Token
Pass a secret or public key to have the API verify the signature:
{
"token": "eyJ...",
"secret": "my-hmac-secret"
}
The response includes "signature_valid": true/false — useful for debugging
auth middleware without spinning up a full application.