JWT decoder and signature verifier
Crypto and hashing
Loading
Loading tool
Preparing the tool. The remaining time is not yet known.
All processing for this tool happens in your browser. Your input is not sent to a server.
About this tool
Read a three-part JWT as formatted Header and Payload JSON, or explicitly verify its signature with a public key you trust. Choose RS256, PS256 or ES256 yourself. Local WebCrypto verification reports the signature separately from exp, nbf, iat, issuer and audience checks. Decoding alone never authenticates a token.
Common uses
- Inspect test-token JSON and copy the Header, Payload or original signature without a key, retaining the existing decoding workflow.
- Diagnose a signature mismatch using a trusted public JWK or SPKI PEM, a pinned algorithm and a synthetic token.
- Reproduce an expiry or audience failure independently of the cryptographic signature, using an explicit reference time and clock tolerance.
How to use it
- 1.Paste only the three-part token, without Authorization: Bearer or surrounding quotes. Decode to inspect and copy JSON; decoding does not require a valid signature.
- 2.For verification, choose the expected RS256, PS256 or ES256 algorithm from your application configuration, not merely from the untrusted alg header. Paste one trusted public JWK or SPKI PEM beginning with BEGIN PUBLIC KEY.
- 3.Set the reference time in Unix seconds and clock tolerance. Supply expected issuer and audience when you want those comparisons; missing expectations leave those checks skipped, never passed. Run verification and read the signature result and each claim result separately. Editing settings, cancelling or clearing invalidates the previous result. Use the application’s own trusted verifier for the final access decision.
Examples
Inspect a synthetic HS256 token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwiaWF0IjoxNzAwMDAwMDAwfQ.fskbbfT8Y-3vjXSxYDdc-fa23GdUmhivjVOFM9NWx8w
{
"sub": "user-42",
"iat": 1700000000
}The output shown is the Payload panel. Header is {"alg":"HS256","typ":"JWT"}; the signature is displayed separately and is not verified.
Read Unicode claims
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoi5L2g5aW9IC8g5pel5pys6KqeIn0.6D1s9ZGSyIcSKLrHkt0c-TQ5z-EXQBbca1LyIGKjSD5nTsgjVxvxt9YDGLSLWJ_hp4GxYVemJchQ7XfXNV6xmQ
{
"name": "你好 / 日本語"
}The Payload preserves UTF-8 text. An HS512 label can be read without a key; this is still not signature verification.
Common errors and checks
- A pasted Bearer prefix, extra dot or missing segment prevents parsing; supply only the three-part token.
- Standard Base64 characters + and /, padding =, invalid UTF-8 or non-object JSON in Header/Payload may fail. JWT uses unpadded Base64url.
- Readable JSON, a future exp value, or an alg label does not prove authenticity or authorization.
Limits and notes
- Decoding keeps the original three-part UTF-8 JSON-object workflow, including display of an empty or altered signature. Verification applies stricter input and key checks. Five-part encrypted JWE, detached payloads and non-object Header/Payload are unsupported.
- Verification supports only RS256 and PS256 with 2048–4096-bit RSA public keys, or ES256 with a P-256 EC public key. PS256 uses a 32-byte salt. The selected algorithm must match alg. HMAC shared secrets, private keys and alg none are rejected; the legacy HS256/HS512 examples below are decoding examples only.
- Paste a single public JWK or SPKI BEGIN PUBLIC KEY PEM. JWK sets, certificates and other PEM types are unsupported. jku, x5u, embedded jwk, x5c, crit and b64 headers are rejected; no remote key lookup or token-directed key selection occurs. Verification accepts only alg, typ, cty and kid header members; kid is a label, not a key lookup. JWK metadata must agree with the selected algorithm and signature verification use. Duplicate JSON names, invalid Unicode and non-canonical Base64url are rejected rather than normalized.
- Claim checks are separate from the signature. NumericDate uses Unix seconds, not milliseconds. Missing or skipped checks are not passes. A matching signature does not establish the owner of an untrusted key, a user’s identity, authorization or revocation status.
- Verification limits: token 64 KiB, public-key text 16 KiB, JSON depth 16 and 4096 nodes, with a 5-second disposable worker deadline. Inputs are processed locally, without upload or storage. Prefer synthetic tokens; real bearer tokens and their claims can contain sensitive information. Encoded segments are separately limited to 4096 Header, 60000 Payload and 1024 signature characters. Expected issuer/audience text is limited to 2048 characters each; clock tolerance must be between 0 and 300 seconds. NumericDate must be a finite JSON number within the safe numeric range; strings and null fail. Missing time claims are reported as missing, and iat is informational, not a freshness policy.
Frequently asked questions
Does successful decoding mean that the signature is valid?
No. Decode only expands the Header and Payload and displays the signature unchanged. Select verification, pin a supported algorithm and supply a trusted public key to check the signature. Even a matching signature is not an authorization decision. The decoder still reads HMAC token JSON, including the legacy examples below. This verifier deliberately accepts public keys only, with RS256, PS256 or ES256. It does not ask for a shared secret or private key and never treats a public key as an HMAC secret.
Can a valid signature coexist with an expired token?
Yes. Worked example: with reference time 1700000100, tolerance 0 and exp 1700000100, the token is expired at that exact second. Its genuine signature can still match. With nbf 1700000101, the token is not yet valid at reference time 1700000100. These time checks do not change the signed bytes. NumericDate values use seconds since the Unix epoch. exp marks expiry, nbf the earliest allowed time and iat the issued-at time. The issued-at check can flag a future value relative to the chosen time and tolerance; it is not a maximum-age, replay or revocation check.
How do issuer, audience and skipped checks work?
Worked example: iss "https://issuer.example" matches that exact expected issuer, and aud ["web","api"] matches expected audience "api". Expected audience "mobile" fails. Leaving an expected issuer or audience blank skips that comparison; a skipped check is not a pass. A token’s self-declared issuer is not evidence that you trust its key.
Which standards define the format and verification boundary?
JWS signing input: RFC 7515 (https://www.rfc-editor.org/rfc/rfc7515.html). Public JWK: RFC 7517 (https://www.rfc-editor.org/rfc/rfc7517.html). Algorithm selection and trust guidance: RFC 8725 (https://www.rfc-editor.org/rfc/rfc8725.html). Browser signature verification: Web Cryptography API (https://www.w3.org/TR/webcrypto/). RFC 7518 and RFC 7519 below define algorithms and claims. This tool implements the documented bounded subset, not every JOSE feature.