Paste a JWT and instantly see its header, payload and signature.
{{ __t('signature_note') }}
{{ __t('empty_state') }}
A JSON Web Token (JWT, RFC 7519) is an open standard for securely transmitting claims between two parties in a compact, URL-safe format. JWTs are used in modern web APIs for authentication and authorization — for example, after login to identify the user on every subsequent request.
Important: A JWT is not encrypted, only signed. Anyone who possesses the token can read its contents. Never store passwords or sensitive data in the payload.
alg.iss — Issuer (who issued the token)sub — Subject (typically the user ID)aud — Audience (intended recipient of the token)exp — Expiration Time (expiry as a Unix timestamp)iat — Issued At (when the token was issued)nbf — Not Before (not valid before this time)Yes. Decoding happens entirely in your browser with JavaScript. No token is sent to any server and nothing is logged. You can inspect the implementation in your browser's developer tools at any time. Still, only paste production tokens in trusted environments.
A JSON Web Token is defined by RFC 7519 as a compact URL-safe representation of claims. The three parts header.payload.signature are each Base64URL-encoded (RFC 4648 §5) — not classic Base64 with + and / but - and _, and without trailing = padding. Decoding therefore means: split on dots, Base64URL-decode each part, parse JSON. That alone validates NOTHING — you only see what is inside the token. Real validation requires three steps: verify the signature, verify the claims, verify the algorithm.
The signature covers the first two segments as base64url(header) + "." + base64url(payload) using the algorithm declared in the alg header claim. HS256 uses HMAC-SHA-256 with a shared secret, RS256 uses RSA-PKCS1-v1.5 with SHA-256 (private key to sign, public to verify), ES256 uses ECDSA P-256, PS256 uses RSASSA-PSS, EdDSA uses Ed25519. When verifying you MUST restrict alg to a whitelist — otherwise an attacker can bypass the signature with alg: none or by swapping the algorithm (CVE-2015-9235, the famous HS256/RS256 confusion bug).
After signature verification comes claim validation. exp (Expiration Time, seconds since Unix epoch) must be in the future, nbf (Not Before) in the past, iat (Issued At) should be plausible. RFC 7519 recommends a leeway window of a few seconds for clock skew between issuer and verifier — most libraries (jose, jjwt, PyJWT) expose this as a parameter. iss (Issuer) and aud (Audience) you MUST check yourself, otherwise you accept foreign tokens: a token issued for service A must not be valid at service B, even if both have the same issuer.
These fields appear in nearly every production JWT. Other claims are allowed but may be implementation-specific.
alg: signature algorithm, e.g. HS256, RS256, ES256, EdDSA, none (never accept). Defined in RFC 7518 (JWA).kid: key ID. Lets the verifier pick the right key from a key set — mandatory for key-rotation setups (e.g. JWKS endpoints in OAuth2/OIDC).exp / nbf / iat: NumericDate values in seconds since the Unix epoch. 1700000000 = 2023-11-14 22:13:20 UTC.iss / aud / sub: issuer, audience, subject. aud can be a string OR an array, which is a common parser-bug source — always handle both shapes.jti: unique token ID. Mandatory for any token blacklist or revocation system; ideally a UUIDv4 or cryptographically secure random string.These header and payload examples show which fields you actually see in real APIs and what they mean.
{"alg":"HS256","typ":"JWT"} — standard header for symmetric signing, typical for self-hosted auth servers or frameworks like Devise (Rails) and Laravel Sanctum.{"alg":"RS256","typ":"JWT","kid":"abc-2024-01"} — asymmetric with key rotation. The kid points to a public key in the JWKS at /.well-known/jwks.json.{"sub":"42","iat":1700000000,"exp":1700003600,"iss":"https://auth.example.com","aud":"api.example.com"} — one-hour access token for user 42 issued by a central auth server.{"sub":"user-7","scope":"read:profile write:posts","exp":...} — OAuth2 scope claim with a space-separated list. Auth servers like Auth0, Keycloak and Okta use this format.{"iss":"https://accounts.google.com","sub":"110...","aud":"client-id","email":"[email protected]","email_verified":true,"nonce":"..."} — the nonce must match the one the client sent.JWT is secure when used correctly — and insecure when not. The classic first bug is alg: none: some libraries accept a token without signature if the header says so. Whitelist algorithms strictly on the server side. Second bug: HS256/RS256 confusion. If the verifier uses the RSA public key as an HMAC secret, an attacker can sign a token with alg: HS256 that "verifies" against the public key. Third bug: no revocation. JWT is deliberately stateless — once issued, valid until exp. If you need logout or token revocation, maintain a blacklist by jti or use short exp + refresh tokens. Fourth bug: too many claims. JWTs end up in cookies, Authorization headers and logs — every claim adds size and pushes you against HTTP header limits (typically 8 KB in nginx). Personal data does not belong in a bearer token because it flows to every resource server that sees it. Fifth bug: no TLS. A JWT without HTTPS is effectively a plaintext session token — whoever captures it is the user.
algorithms parameter explicitly, never trust the token's own alg header. Fetch the public key/secret externally, ideally via JWKS.exp reaches now?jti, or a global "min issued at" timestamp per user that invalidates all earlier tokens. Both undo the stateless benefit.Secure and SameSite=Lax, because JavaScript cannot read it (XSS-safe). LocalStorage is vulnerable to XSS but is the default in many SPA architectures. Never in the URL — it ends up in server logs, Referer headers and browser history.header.payload.signature shape with exactly two dots. Common causes: whitespace, a duplicated Bearer prefix in the Authorization header, token truncated due to header-size limits or an empty string because the cookie was not set yet.