JWT Debugger for QA & API Testers
Decode any JWT, verify HS256 / RS256 / ES256 signatures, and run a vulnerability audit (alg=none, weak secrets, jku/kid abuse, sensitive claims). One-click export to Postman, Playwright, Rest Assured, cURL. Your tokens never leave the browser.
{
"alg": "HS256",
"typ": "JWT"
}{
"sub": "1234567890",
"name": "QA Tester",
"admin": true,
"iat": 1516239022,
"exp": 9999999999
}tPZTgH0YlrbShvXqxr_DjZNGgcVh3jNxwCxdo3f7ChM
Header alg=HS256 — paste the shared secret below.
Secret is 19 bytes — for HS256 use ≥ 32 bytes (256 bits) or it's brute-forceable.
Checks OWASP JWT Cheat Sheet + RFC 8725 anti-patterns. Findings map to real CVE classes.
Token TTL is ~98192 days (8483760977s). Bearer tokens should be short-lived.
Fix: Drop access-token TTL to ≤15 minutes and rely on refresh tokens for continuity.
iss identifies your auth server. Without it you can't safely verify a token came from the expected issuer.
Fix: Require iss and validate it against a fixed allow-list in the verifier.
aud binds the token to a specific API. Without it, a token minted for Service A works for Service B.
Fix: Require aud and validate the API-specific value on every request.
Header uses HS256. Anyone with the secret can mint tokens. Fine for internal service-to-service; risky for public APIs.
Fix: For public APIs use RS256 or ES256 so only the auth server holds the private key.
// Postman → Pre-request Script
// Auto-refreshes the JWT if within 60s of expiry.
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlFBIFRlc3RlciIsImFkbWluIjp0cnVlLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6OTk5OTk5OTk5OX0.tPZTgH0YlrbShvXqxr_DjZNGgcVh3jNxwCxdo3f7ChM";
const [, payloadB64] = token.split(".");
const pad = "=".repeat((4 - (payloadB64.length % 4)) % 4);
const payload = JSON.parse(
Buffer.from((payloadB64 + pad).replace(/-/g, "+").replace(/_/g, "/"), "base64").toString()
);
const nowSec = Math.floor(Date.now() / 1000);
if (!payload.exp || payload.exp - nowSec < 60) {
// TODO: call your /refresh endpoint here
console.warn("JWT expiring soon — implement refresh");
}
pm.request.headers.upsert({ key: "Authorization", value: "Bearer " + token });Why this JWT debugger beats jwt.io for QA teams
Vulnerability audit (15 checks)
alg=none, weak HS secret, missing exp, long-lived TTL, jku/x5u/jwk header abuse, kid path traversal, sensitive claims — with the exact remediation for your framework.
Live expiry countdown
iat / nbf / exp shown as ISO plus 'in 12m' / '4d ago'. VALID / EXPIRED badge updates every second so you never chase a stale token bug.
HS + RS + ES verify locally
WebCrypto verifies HS256/384/512 with a secret and RS256/384/512 + ES256 with a JWK. No round trip to a server.
Postman & Playwright export
Pre-request script that auto-refreshes near exp, Playwright request context, Rest Assured spec, cURL, Axios, Fetch — copy-paste ready.
Sample attack tokens
alg=none, expired, 10-year TTL, jku SSRF, kid path-traversal. Load one, run the audit, rehearse the fix before it ships.
100% local — safe for prod tokens
Zero network calls. Security teams that block jwt.io internally allow this tool because your bearer tokens and HS secrets never leave the tab.
How QA engineers use this JWT debugger
- Load the 'alg=none' sample.
- Send it to your protected endpoint via Postman/Playwright.
- Assert 401. If you get 200 — file a P0.
- Repeat with 'expired', 'jku', and 'kid path traversal'.
- Paste your JWT and open Export → Postman.
- Copy the pre-request script into your collection's Auth folder.
- Set token in a collection variable.
- Refresh logic runs automatically when exp is 60s away.
- Paste id_token from your login.
- Export → Playwright request context.
- Drop into fixtures.ts as an authenticated api fixture.
- Reuse across every API spec.
- Paste bearer token.
- Export → Rest Assured.
- Wrap in a RequestSpecBuilder singleton.
- Add negative-path test asserting 401 with tampered payload.
JWT claims & algorithms cheat sheet
Registered claims
| iss | issuer |
| sub | subject / user id |
| aud | audience / API |
| exp | expiry (unix seconds) |
| nbf | not before |
| iat | issued at |
| jti | unique token id |
Header fields
| alg | signing algorithm |
| typ | usually JWT |
| kid | key id (for JWKS) |
| jku | AVOID — SSRF risk |
| x5u | AVOID — SSRF risk |
| jwk | AVOID — trust attack |
| cty | content type |
Algorithms
| HS256/384/512 | HMAC — shared secret |
| RS256/384/512 | RSA + SHA — public/private |
| ES256/384 | ECDSA — public/private |
| PS256/384 | RSA-PSS |
| EdDSA | Ed25519 |
| none | NEVER — always reject |
Common CVEs
| alg=none bypass | CVE-2015-9235 class |
| RS→HS confusion | CVE-2016-10555 |
| kid path traversal | auth bypass |
| jku SSRF | OWASP JWT §6 |
| weak HS secret | hashcat 16500 |
Recommended TTLs
| Access token | 15 min |
| Refresh token | 7-30 days |
| Password reset | 15 min |
| Email verify | 24 h |
| Service token | 1 h max |
Providers
| Auth0 | /.well-known/jwks.json |
| AWS Cognito | /.well-known/jwks.json |
| Okta | /oauth2/default/v1/keys |
| Firebase | securetoken jwks |
| Keycloak | /realms/{r}/protocol/openid-connect/certs |
Pair this with
cURL to Code Converter
Convert a cURL with Authorization: Bearer into Postman, Playwright, or Rest Assured — then debug the JWT here.
JSON / JSONPath / JMESPath Tester
Assert JWT-protected response bodies with side-by-side JSONPath and JMESPath queries.
Postman to Code Converter
Migrate a Postman collection into Playwright / Rest Assured / k6 while preserving Bearer token auth.
Regex Tester for QA
Validate the JWT format itself (`^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$`) in your assertions.
API Testing Interview Q&A
60+ Q&As including OAuth 2.0 flows, refresh-token rotation, and JWT verification pitfalls.
Postman Interview Q&A
Deep dive on pre-request scripts, environment variables, and Bearer token automation.