⭐ 0

JWT Token Debugger

Decode a JWT header and payload, and compare the signature with HMAC-SHA256 of the secret you type.

🔒 Processed entirely in your browser — nothing you enter here is ever uploaded.

The result appears on this page after you run the tool. Nothing you enter is uploaded.

Processing... 0%
Parsing token segments
Extracting JSON metadata
Verifying signature schema
Done

Result

About this tool

Paste a token of three base64url segments separated by dots. Fewer or more segments mark the signature invalid and clear any countdown. Each of the first two segments is decoded by turning - into + and _ into /, adding padding, and calling atob, then UTF-8 decoding the bytes. The results must be JSON. The header box and the payload box receive JSON.stringify with two-space indentation. If the payload has a numeric exp, a badge counts down to that Unix second using the local clock, once a second. When the clock passes it, the badge says the token is expired and the interval stops. A payload with no numeric exp removes the badge.

The signature check does not read the alg claim. It always imports the secret box as a raw HMAC key with SHA-256 and signs the exact characters header-dot-payload. The signature is base64url without padding. If those characters equal the third segment, the badge says the signature was verified. Otherwise it says the signature is invalid. An empty secret is still a key: HMAC of the empty string. A token signed with a different secret, or with RS256 or ES256, will not match, because this page never loads a public key and never checks an RSA or ECDSA signature. Treat a green badge as HMAC-SHA256 agreed with the typed secret, not as proof that the header's alg was honored.

A known test vector is the header {"alg":"HS256","typ":"JWT"} and the payload {"sub":"1234567890","name":"Ada","exp":2000000000} signed with the secret secret. The token is eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFkYSIsImV4cCI6MjAwMDAwMDAwMH0.VfojGxqMm4geMzxQk_36J5jJvX0Hzsg5cRtZCHyl66E. With that secret the badge matches. exp 2000000000 is the instant 2033-05-18T03:33:20.000Z, so the countdown runs until then. Change one character of the secret and the badge fails, while the decoded JSON stays, because decoding does not depend on the signature. The rebuild path parses the two JSON boxes, stringifies them with no extra space, base64url-encodes those strings, and signs them with the same HMAC-SHA256 helper. The output is a new three-part token, and the badge is set to valid for that new token. Editing the JSON and rebuilding replaces the original bytes. It does not preserve the original signature. The secret is used only inside this page's Web Crypto call. It is not sent anywhere. The page does not store a token, does not check nbf or aud, and does not decode a nested JWT. A payload that is not JSON fails the decode and clears the countdown.

Example. Header {"alg":"HS256","typ":"JWT"} and payload {"sub":"1234567890","name":"Ada","exp":2000000000} with secret secret produce eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFkYSIsImV4cCI6MjAwMDAwMDAwMH0.VfojGxqMm4geMzxQk_36J5jJvX0Hzsg5cRtZCHyl66E and a matching HMAC badge. exp is 2033-05-18T03:33:20.000Z.

Limit. The signature check is always HMAC-SHA256 of the secret you type. The alg header is not honored, so RS256 and ES256 cannot verify here. nbf, aud, and iss are not checked.

How do I check the sample HMAC token?

Paste the three-part token in the example and type the secret secret. The header and payload boxes fill with the pretty JSON, the signature badge matches, and the exp countdown aims at 2033-05-18T03:33:20.000Z. A different secret fails the badge and still shows the JSON.

Will this verify an RS256 token?

No. The check always recomputes HMAC-SHA256 with the secret box and compares it to the third segment. It does not read alg, and it has no public-key field. An RS256 or ES256 token will not get a green badge from its real key. A green badge means the HMAC matched the typed secret.

What does the expiration badge use?

Only a numeric exp, interpreted as Unix seconds. The badge updates every second until that instant, then it says the token is expired. nbf, iat, aud, and iss are displayed if they are in the JSON, and they are not compared with anything.

What happens when I edit the JSON and rebuild?

The boxes are parsed, re-stringified without pretty spacing, and signed with HMAC-SHA256 of the current secret. The new token replaces the output. The original signature is not kept. The secret stays in the page.