JWT Parser
Parse the JWT header and payload, and check the expiry time
JWT parsing and security: decoding is not the same as trusting
The structure of a JWT
A JWT is three Base64url segments joined by dots: header.payload.signature.
- header: the algorithm and token type, for example
{"alg":"HS256","typ":"JWT"}. - payload: the claims, which are the actual data.
- signature: a signature over the first two segments, proving the content was not altered.
All three segments use Base64url encoding — the alphabet swaps - and _ in for + and /, and it strips the trailing = padding. That is why feeding a JWT to a standard Base64 decoder fails.
The first lesson: decode is not verify
The payload is merely Base64, so anyone can read it with no key at all. Drop it into any JWT parser and you see what is inside.
The reverse point matters more: recognizing the contents does not make the token trustworthy. Real trust comes from verifying the signature, and verification needs the secret or public key held by the server — something a browser cannot do. So what an online parser can honestly tell you is "here is what the token contains", not "this token is valid".
This leads straight to the first discipline of using JWTs: never put sensitive data in the payload. It is as readable as plaintext. JWE (the encrypted form of JWT) provides confidentiality, but it is a different mechanism from the common JWS.
Standard claims
| Field | Meaning | Common pitfall |
|---|---|---|
iss | Issuer | Must be checked, or any issuer sharing the key name can impersonate |
sub | Subject (usually a user id) | Do not use it directly as a database primary key without mapping |
aud | Audience | Required when several services share one key, to stop service A's token calling service B |
exp | Expiry (Unix seconds) | Server clock drift can mark a freshly issued token as expired |
nbf | Not valid before | Often ignored, causing early use to be rejected |
iat | Issued at | Useful for rejecting long-lived tokens issued long ago |
jti | Unique token id | Blacklists and revocation depend on it |
All time fields are Unix seconds, not milliseconds. Getting the unit wrong makes exp land in the year tens of thousands or back in 1970 — one of the most common bugs people hit while debugging (most parsers render the time fields as readable dates, so just look at them).
Algorithm choice and known attacks
| alg | Type | Key shape | Note |
|---|---|---|---|
| HS256 | Symmetric HMAC | Shared secret | Fast, but the verifier can also sign |
| RS256 | RSA signature | Private signs, public verifies | Common across services; public key can be published |
| ES256 | ECDSA signature | Private signs, public verifies | Shorter key and shorter signature |
| none | No signature | — | Early libraries accepted it, meaning zero protection |
Several real vulnerability patterns are worth knowing:
- alg confusion (RS256 to HS256). The server expects RS256 and verifies with a public key; an attacker flips the header to
HS256and then signs using the published public-key text as the HMAC secret. If the library picks the verification method from the header's alg, it computes HMAC with the public key and passes. Defense: the server pins the expected algorithm and never trusts the token's self-declared alg. - alg set to none. The signature segment is simply dropped. Modern libraries reject it by default, but hand-rolled implementations often miss the check — always reject
noneexplicitly. - Weak HMAC secret. If the HS256 secret is a short passphrase or common word, it can be brute-forced offline — an attacker who grabs any valid token can try secrets locally without touching your server. The secret must be a long random value.
- kid injection. If the
kidheader is concatenated into a file path or SQL query, it becomes a path-traversal or injection vector.
A debugging walkthrough
- Read the header's
algand confirm it matches what the server expects. - Inspect
exp/nbf/iat, convert the time fields to your local time, and compare against the server clock. - Check that
audandissbelong to this service. - Work out where the token is stored: if it lives in
localStorage, any XSS can read it; anHttpOnlycookie is unreadable by script but needs CSRF handling. - Only last, suspect the signature — a signature error usually means inconsistent key configuration, such as multiple instances reading different key files.
This tool only decodes locally and shows the structure; it sends no token and performs no signature verification (that needs a key and should not be handed to a third-party site). For any production token, do not paste it into any online tool, including this one — use your own local debugging instead.
FAQ
Why can it not verify the signature?
Signature verification needs the server secret (HS256) or a public key (RS256) plus the verification logic. Client-side parsing is only for viewing content.
Could the token leak?
No, parsing runs entirely locally in your browser. Still, we recommend never pasting a real production token into any website, including this one.