What the JWT HS256 Verifier Does
The JWT HS256 Verifier performs a real cryptographic signature check on an HMAC-SHA256-signed token — in your browser, with the shared secret you supply. Paste the complete token into the input panel, enter the secret in the Secret field in the options bar, and run the transform. The output is a one-line verdict: ✓ Signature valid (HS256) when the recomputed signature matches the token's, or ✗ Signature does NOT match when it does not.
Unlike the RS256 path — where browser-side verification is withheld because key authority matters — HS256 verification is exactly what a browser page can do honestly: the secret is a shared string, the check is a symmetric HMAC comparison, and Web Crypto performs it natively. The tool imports your secret as an HMAC-SHA256 key, computes the signature over the token's header.payload bytes, decodes the token's Base64Url signature, and compares the two. There is no approximation and no placeholder — this is the same operation your auth server performs.
Empty secrets are rejected with an explicit error — the tool will not "verify" against an empty key. And the verdict covers only the signature: the tool does not evaluate claims, expiry, issuer, or audience. A perfectly signed token with an expired exp verifies successfully here, which is correct behaviour and the clearest demonstration that authenticity and validity are separate checks.
How the HS256 Verification Works
HS256 signatures are HMACs — Hash-based Message Authentication Codes — computed with SHA-256. An HMAC is a keyed hash: it hashes the message twice, once with the key folded into an inner pad and once into an outer pad, producing 32 bytes that are indistinguishable from random to anyone lacking the key. JWTs sign the string header.payload — the Base64Url segments joined by a dot, without a trailing dot.
Verification recomputes that HMAC and compares. The tool's path: import the secret as a raw HMAC / SHA-256 key in Web Crypto; Base64Url-decode the token's third segment (mapping - back to +, _ to /, restoring stripped padding); then call crypto.subtle.verify, which performs the comparison in constant time — the timing-safe comparison that prevents an attacker from learning how many leading signature bytes matched. The boolean it returns is the verdict.
Constant-time comparison deserves its sentence: a naive byte-by-byte equality check leaks information through how quickly it fails. Web Crypto's verify compares all 32 bytes regardless, so response timing reveals nothing about where a mismatch begins — invisible when present, catastrophic when absent.
What verification proves, precisely: the holder of the secret produced (or countersigned) this exact header.payload pair. What it does not prove: that the secret holder is who you think it is (did you paste the right secret for this issuer?), that the claims are currently true (the token may be expired or revoked), or that the algorithm is even HS256 — the tool's verification assumes the token's signature segment is an HMAC; a token claiming
alg:RS256 will simply fail, but the informative failure is the
JWT RS256 Verifier's inspection report.
Using the JWT HS256 Verifier
- Step 1 — Paste the complete token. All three dot-separated segments, exactly as received. Truncated tokens fail the decode rather than the signature check, so a malformed paste is distinguishable from a wrong secret.
- Step 2 — Enter the secret. In the options bar's
Secret field, type the shared secret exactly — case, length, and every character. HMACs are unforgiving: Secret1 and secret1 produce entirely different signatures. - Step 3 — Run the transform. One verdict line comes back. No report, no claims dump — the signature either matches or it does not.
- Step 4 — Interpret the two outcomes. A valid signature means this token's header and payload are byte-for-byte what the secret holder signed. A mismatch means one of: the token was modified after signing, the secret is wrong, or the token is not HS256 at all. Work through them in that order.
- Step 5 — Check the rest of the token separately. Signature authenticity does not cover lifetime. Run the same token through the JWT Validator or JWT Expiry Checker before treating its claims as currently trustworthy.
Common Use Cases
Confirming a token's provenance during debugging. When an API accepts your token but behaves oddly, verification separates "the token is not what the server issued" from "the token is genuine but its claims mislead you." One run answers the provenance half.
Testing signature-verification logic offline. Building an auth middleware? Generate tokens with the
JWT Generator using a known secret, then verify them here — the round trip exercises the exact trust boundary your middleware implements, without standing up an auth server.
Demonstrating tamper-evidence. Flip one character in a token's payload and verify: the signature fails, though the token still parses. It is the single most instructive JWT demonstration, and it takes thirty seconds with this tool and the generator.
Sanity-checking secret rotation. After rotating a signing secret, verify an old token (should fail against the new secret) and a new one (should pass). Both outcomes in one minute beats a day of intermittent auth failures in staging.
Worked Example
Take this token — generated with the secret secret, claims fully readable in its payload:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.1VAmegkQOBsQ-iSZU96z6c8NY7QR9OhhYWYHwHTeGT4
Enter secret in the Secret field and run the transform:
✓ Signature valid (HS256)
The verification recomputed HMAC-SHA256 over the 36-character header, a dot, and the 74-character payload — using your secret — and compared the 32-byte result against the 43-character Base64Url signature. Identical, hence valid. This token's claims are now cryptographically attributable to whoever held secret when it was signed.
Three failures are worth reproducing, each teaching something different. Change the secret to
Secret (capital S): mismatch — HMAC output is wholly different, case matters absolutely. Change one character in the payload segment — say the
name claim: mismatch, even though the token still decodes to valid JSON; this is tamper-evidence in action. Keep the secret but paste a token whose header says
alg:RS256: mismatch again, and the right response is inspection with the
JWT RS256 Verifier, not more secret guessing.
Tips and Common Mistakes
- Secret mismatch is the most common failure. Before concluding a token is forged, verify you pasted the secret exactly: no trailing space, no case slip, no smart-quote substitution from copying through a document. Nine wrong-secret reports out of ten are paste artefacts.
- A valid signature says nothing about expiry. The tool checks authenticity only. Expired, revoked, and not-yet-valid tokens all verify successfully — lifetime belongs to the JWT Validator.
- Non-HS256 tokens simply fail. There is no algorithm auto-detection: the verification assumes an HMAC signature. If you suspect the token is RS256 or ES256, inspect its header first rather than concluding the secret is wrong.
- Handle the secret with the same care as the token. The tool runs locally and transmits nothing, but pasting production signing secrets into any browser page deserves the same discipline as pasting the tokens themselves: prefer test secrets, and rotate anything you have pasted somewhere questionable.
- Paste the whole token. The signature covers
header.payload exactly; verifying a fragment is meaningless. Whitespace around the token is trimmed, but any edit inside it changes what is signed. - Timing attacks are already handled. The comparison runs through Web Crypto's constant-time verify, so repeated attempts cannot extract signature bytes by timing. The security boundary here is the secret's confidentiality, nothing else.
Frequently Asked Questions
Is verifying a JWT in the browser actually safe?
The computation is — it happens locally in Web Crypto, with no network involvement, and neither the token nor the secret leaves the page. The operational caution is about the secret, not the maths: pasting a production signing secret into any browser context is a decision to make deliberately. For production secrets, prefer verifying on infrastructure you control; use this tool with test secrets, or with secrets you are prepared to rotate.The signature fails but I am sure the secret is right — what else?
In rough order of likelihood: the token was modified after signing (even one payload character); the token is not HS256 (check the header's
alg); the token was truncated or whitespace-mangled in transit; or the secret genuinely differs — different environment, rotation timing, or a staging/production split. The
JWT Decoder shows the header's algorithm when you need to rule the second cause in or out.
Why does an expired token still verify as valid?
Because signature validity and temporal validity are independent properties, and conflating them is how auth bugs hide. The signature proves the issuer signed these claims at some point; it says nothing about whether those claims are current. Production systems verify the signature first and then check exp, nbf, and revocation separately — this tool deliberately mirrors the first step only.Can I verify RS256 or ES256 tokens here?
No — the tool performs HMAC verification only. RS256 verification needs the issuer's RSA public key and the RSA maths, which belongs in your service where key trust is enforceable; the
JWT RS256 Verifier provides the inspection half of that workflow. ES256 (ECDSA) likewise requires its own key type and verification path.
Does the tool tell me which claims failed?
No claim is evaluated at all — the output is purely the signature verdict. If you need the claims beside the verdict, decode the token first with the
JWT Decoder, then verify here. Keeping the two outputs separate mirrors how verification and validation actually compose in production code.
Related Tools
JWT Generator mints HS256 tokens with a secret you choose — the natural counterpart for round-trip testing;
JWT Decoder reveals the claims behind a verdict;
JWT Validator and
JWT Expiry Checker cover the lifetime checks verification leaves out; and
HMAC Generator exposes the raw HMAC primitive underneath, if you want to see the signature computation without the JWT framing.