Debugging JWT Authentication: A Practical Guide

Security

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.

Try it out

Browse Tools →

More from the Blog