Skip to content

2026-08-01 · 9 min read

JWTs in practice: RFC 7519 without the hand-waving

How JSON Web Tokens are structured, which claims matter, why alg none is dangerous, and how to inspect tokens without leaking them to a hosted debugger.

A JWT is three strings and a lot of policy

The compact serialization is `header.payload.signature`, each part base64url-encoded. The header names an algorithm. The payload is a JSON object of claims. The signature is computed over the first two segments. RFC 7519 defines registered claim names but does not tell you how to store the token, how long it should live, or whether it belongs in a cookie or in memory. Those choices are where most incidents happen. Treat a JWT as a bearer credential: whoever holds it can call your API until `exp`. Decode is free; verify is the part that matters. PureDevKit’s debugger only decodes unless you optionally supply an HMAC secret for HS256 — and you should never paste a production private key into any webpage, including this one on a shared computer.

Claims you should actually enforce

`iss` and `aud` bind a token to an issuer and an intended audience. If you skip audience checks, a token minted for your marketing site might be accepted by your admin API. `exp` is a Unix timestamp in seconds, not milliseconds — mixing the two produces tokens that expire in 1970 or in the year 50 million. `nbf` is useful for tokens that must not work until a future instant. `jti` plus a denylist lets you revoke a specific token before expiry. Put stable identifiers in `sub`, not email addresses that people change. Do not put passwords, full card numbers, or session secrets in the payload: it is encoded, not encrypted. If the payload must be confidential, you want JWE or you want the data to stay on the server.

Algorithms and the none attack

HS256 is HMAC-SHA-256 with a shared secret. RS256 and ES256 use asymmetric keys so a resource server only needs the public key. The historical `alg: none` attack works when a verifier takes the header’s algorithm at face value and skips the signature. Your verifier must use an allow-list (`HS256` or `RS256`, not “whatever the token says”). Key ids (`kid`) help with rotation but must not be used as file paths. Rotate secrets when they leak — and assume a token pasted into a public JWT debugger has leaked. Inspect tokens locally instead.

Browser storage

`localStorage` is easy and XSS-complete: any script on the origin can read the token. httpOnly, Secure, SameSite cookies are usually better for session JWTs on first-party sites, with CSRF defenses if you use cookies. For SPAs talking to APIs on another origin, BFF patterns (the browser talks only to your backend, which holds the session) reduce token exposure. Short access tokens plus rotating refresh tokens beat a one-week JWT in `localStorage`. None of this is visible in the encoded payload — it is architecture around the token.

Related tools