Skip to content
Tools Without AI

Prefer toolswithoutai.com in Google Search so our tools and guides show up more often. Google has to confirm it — we cannot set this for you.

Formatting standards · · updated

JWT security: decode tokens locally and do not paste secrets

A JWT in compact form is three base64url segments. Decoding header and payload is a string split plus JSON.parse. That does not prove the signature. Pasting a live token or HMAC secret into a cloud debugger hands the session to that site. Inspect with the JWT inspector. Verify HMAC locally with the HMAC generator only when you already hold the key.

JWS compact serialization

base64url without padding. Header.payload.signature. Header holds alg and typ. Payload holds claims. Signature is HMAC or asymmetric over ascii(header)+'.'+ascii(payload). Base64 vs Blobs explains why this encoding is fine for tokens and terrible for 40 MB files. The Base64 encoder is the general tool; JWT needs the URL alphabet and missing padding.

Decode is not verify

Replace -_ , add padding, JSON.parse. Stop there for debugging claims in the JWT inspector. HMAC verify is a different button and needs the secret in Web Crypto. If you paste the HS256 secret into a website, rotate it.

Claims: exp, nbf, aud

NumericDate as seconds. Leeway of a few minutes is common. aud must match the resource. Tokens in query strings also need percent-encoding care so they are not split on &. Do not put bearer tokens in URLs if you can use a header.

Why jwt.io-style paste is an incident

Access tokens are bearer credentials. Support dumps, HAR files, and “please decode this” Slack threads are the same class. Use the local inspector. HTML sinks are how a debug page that innerHTML’s a claim named “name” becomes XSS.

When you own the secret

HMAC-SHA256 via subtle.importKey + sign, documented in HMAC via Web Crypto. Asymmetric verify needs the public JWK. Still in-tab if the key is already on the device. The HMAC generator is the primitive, not a JWT library.

Tools

JWT inspector, HMAC generator, Base64 encoder, URL encoder if the token is stuck in a query.

Worked example: a failing exp claim

Paste the token into JWT inspector. Read exp as Unix seconds. Convert with epoch converter (epoch vs ISO). If you treated exp as milliseconds, it is a date in 1970. If the laptop clock is wrong, local debug lies; the verifier’s clock is what production uses.

alg HS256: do not paste the secret into a website. Recompute with HMAC generator on ascii(header)+'.'+ascii(payload) using your local secret, as in HMAC via Web Crypto. Compare signatures. alg none: reject.

Token in a URL: decode query with URL encoder so percent-encoding does not split the JWT. Prefer headers. Logging the URL logs the bearer token.

Displaying sub or name in HTML: escape (DOM XSS). A claim is not a safe HTML fragment. Network quiet while you inspect: the token should not become a POST body to our origin.

Frequently asked questions

Does decode prove the token is valid?

No. Anyone can mint a JSON payload. Validity is signature plus exp/nbf/aud checks. HMAC is how HS256 is computed.

What is the alg none attack?

A token that declares alg=none and has an empty signature. Verifiers that trust the header blindly accept it. Never take alg from the token as the sole truth.

Why do tokens fail at midnight?

exp is Unix seconds. Clock skew between issuer and verifier, or seconds vs milliseconds, is the usual bug. See epoch vs ISO 8601.