2026-10-21 · 8 min read
- jwt
- auth
- tooling
The JWT page decodes a token in the browser and can mint a test token with HS256 or RS256. Generation is local. Decode shows the first two segments. Neither action verifies a signature against a trusted key, and the page says so under the token box.
The header that gets signed is the header object after the selected algorithm is written in. Comparing a draft that still says none with the decoded result is the whole check.
Let the button own alg
Both boxes must be JSON objects. Arrays, null, and JSON strings throw Header and payload must be JSON objects. The header is then serialized with alg set to HS256 or RS256. A missing alg key is added at the end. An existing alg key keeps its position and loses its old value. typ is left as you typed it during Generate.
The HS256 and RS256 buttons also edit the header box. They set alg, set typ to JWT, and pretty-print at two spaces. If the box is not currently valid JSON, the button replaces it with a new object that contains only alg and typ. Fix a trailing comma before you switch algorithms if the rest of the header matters.
- Generate, then decode the result.
- Confirm alg matches the button.
- Confirm claims survived in the payload.
- Treat a replaced header box as a new draft.
Feed the signer a key it can import
HS256 uses the shared-secret string as UTF-8 bytes. An empty secret throws Enter a shared secret for HS256. The development default is the literal change-me-development-secret. Generate secret fills the box with 32 random bytes encoded as base64url. That text is still used as characters, not decoded back to the 32 bytes, unless your API does that decode itself.
RS256 requires a PKCS#8 PEM whose armor says PRIVATE KEY. The importer strips that label and the matching END line, removes whitespace, and base64-decodes the rest. BEGIN RSA PRIVATE KEY is a different label, so the armor remains and the decoder throws Invalid character. An empty box throws Paste a PKCS#8 private key PEM first. The public key box is exported for you to configure a verifier. It is not used when the page signs.
Read decode as a viewer
The token is trimmed. A blank box clears the panels. Fewer than two segments shows Not a JWT (expected header.payload.signature). Two segments decode. Extra segments after the signature are ignored, so a pasted trailing dot does not by itself blank the panels. JSON segments are pretty-printed at two spaces with a trailing newline. Other text is shown as decoded bytes. Bad base64url shows Invalid character.
A payload of the letters hello stays hello. It does not gain a newline. A payload that is JSON gains the trailing newline the formatter adds. Copy copies the panel, newline included.
Keep the fixture out of production logs
Use a generated secret or a generated RSA pair, download the PEM if you need it in a local verifier, and delete it when the ticket is done. Do not paste a production signing key into the page.
Use the JWT tool for the token, the JSON formatter for the claims, the Base64 tool after you have turned a segment back into standard alphabet, and the PEM newline tool when a PKCS#8 key was stored with escaped newlines. The API still has to check the signature, iss, aud, and exp.