What Is a JSON Web Token (JWT)?

A JSON Web Token (JWT, pronounced "jot") is a compact, URL-safe way to represent claims between two parties. Defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519), JWTs are the dominant token format for modern authentication and API authorization, you'll find them in OAuth 2.0 bearer tokens, OpenID Connect ID tokens, session cookies, and service-to-service API keys.

Unlike opaque session tokens (which are random strings your server looks up in a database), a JWT is self-describing: its payload carries the user's identity, permissions, and expiry directly inside the token. The server verifies the cryptographic signature rather than doing a database round-trip, which makes JWTs attractive for stateless, horizontally-scalable architectures.

The Three-Segment Structure

Every JWT is three Base64URL-encoded segments separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTcxNzAwMDAwMH0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header

The first segment is a JSON object describing the token's metadata:

{
  "alg": "HS256",
  "typ": "JWT"
}

alg tells the receiver which algorithm was used to sign the token. Common values: HS256 (HMAC-SHA-256, symmetric), RS256 (RSA-PKCS1v1.5, asymmetric), ES256 (ECDSA P-256, asymmetric), PS256 (RSA-PSS, asymmetric). The typ field is almost always "JWT".

Payload

The second segment contains the claims, statements about the subject and any additional application data:

{
  "sub": "user_123",
  "name": "Ada Lovelace",
  "iss": "https://auth.example.com",
  "aud": "my-app",
  "iat": 1717000000,
  "exp": 1717003600
}

Signature

The third segment is the cryptographic signature over base64url(header) + "." + base64url(payload). For HMAC algorithms the server holds the shared secret; for RSA/ECDSA algorithms the server holds the private key and clients verify with the public key. The signature is what prevents tampering, changing any byte in the header or payload invalidates it.

Important: Base64URL encoding is NOT encryption. Anyone who holds the token can decode the header and payload without any key. Never store sensitive data (passwords, credit card numbers, PII beyond a user ID) in JWT claims.

Standard Claims (RFC 7519)

Claim Full name Meaning
`iss` Issuer Identifies who issued the token (e.g. `https://auth.example.com`)
`sub` Subject The principal the token refers to, typically a user ID
`aud` Audience Intended recipient(s), your API should reject tokens not addressed to it
`exp` Expiration Time Unix timestamp after which the token must be rejected
`nbf` Not Before Unix timestamp before which the token must be rejected
`iat` Issued At Unix timestamp when the token was created
`jti` JWT ID Unique identifier; useful for one-time tokens and revocation lists

Application-specific claims (e.g. role, email, permissions) can be added freely alongside the standard ones.

Signing Algorithms: HS256, RS256, ES256

HS256 / HS384 / HS512 (HMAC-SHA)

Symmetric: the same secret is used to sign and to verify. Simple to implement, but every party that needs to verify tokens must hold the secret. Suitable for first-party APIs where the issuer and validator are the same service. Never expose the secret to clients.

RS256 / RS384 / RS512 (RSA)

Asymmetric: the issuer signs with a private key; verifiers use the corresponding public key. Public keys can be published safely via JWKS endpoints (/.well-known/jwks.json). Suitable when third parties need to verify tokens without trusting them with signing capability. Key size: at least 2048-bit RSA.

ES256 / ES384 / ES512 (ECDSA)

Asymmetric like RSA but with much shorter keys and signatures for the same security level. ES256 (P-256 curve) produces 64-byte signatures vs RS256's 256-byte signatures. Preferred for bandwidth-constrained environments (mobile, IoT). Requires careful implementation, a biased nonce is a critical vulnerability in ECDSA.

PS256 / PS384 / PS512 (RSA-PSS)

RSA with probabilistic padding (PSS), more secure than PKCS1v1.5 (RS256) and preferred by newer standards like FAPI. If you have a choice between RS256 and PS256 with the same key, use PS256.

Security Considerations

Never trust `alg: none`

The none algorithm means "no signature", some early JWT libraries would accept a token with "alg":"none" and no signature as valid, allowing trivially forged tokens. Your server must have an explicit allowlist of accepted algorithms and must reject none unconditionally.

Always validate `alg` server-side

Do not let the client's token header dictate which algorithm your server uses to verify. Pin the expected algorithm in your library configuration (e.g. jwt.verify(token, secret, { algorithms: ['HS256'] })). The "algorithm confusion" attack (switching RS256 to HS256 with the public key as the HMAC secret) is real and exploitable.

Validate `exp`, `nbf`, and `aud`

Expiry validation prevents replay attacks with stale tokens. Audience validation prevents a token issued for Service A from being accepted by Service B. Most libraries do these checks automatically, make sure you haven't disabled them.

Keep JWTs short-lived

The longer a token lives, the longer the window if it's stolen. Access tokens: 5–15 minutes. Refresh tokens: days to weeks, stored server-side with revocation support. If you need long-lived sessions, use refresh token rotation rather than a long-lived access token.

Do not store JWTs in localStorage for sensitive applications

localStorage is accessible to any JavaScript on the page, making it vulnerable to XSS. For high-security applications, store JWTs in HttpOnly; Secure; SameSite=Strict cookies, JavaScript cannot read them, so a successful XSS attack cannot exfiltrate the token directly.

Signature verification requires the key

The payload is public by design, this tool decodes it without any key. But to confirm a token was issued by a specific party and has not been tampered with, you must verify the signature using the issuer's secret (HMAC) or public key (RSA/ECDSA). Decode-only inspection is useful for debugging expiry, claim values, and algorithm, not for authorization decisions.

How This Tool Helps

Paste any JWT into the input and the decoder instantly:

  • Splits the three segments and Base64URL-decodes header and payload
  • Shows the raw JSON for both, formatted and indented
  • Detects exp and displays a human-readable expiry status (VALID / EXPIRED / NOT YET VALID / NO EXPIRY) with the exact UTC timestamp and relative time ("2h ago", "5d from now")
  • Surfaces iat and nbf with the same human-readable treatment
  • Lists every claim with its RFC description for standard claims
  • Identifies the signing algorithm and categorises it (symmetric / asymmetric)
  • Shows the raw base64url signature segment for reference

Everything runs entirely in your browser, the token is never sent to any server. This makes the tool safe to use with production tokens during debugging.

Frequently asked

Is a JWT encrypted? Can anyone read the payload?

No — JWTs are signed, not encrypted by default. The header and payload are only Base64URL-encoded, which is trivially reversible without any key. Anyone who holds the token can decode and read the claims. Never store passwords, credit card numbers, or sensitive PII in JWT claims. If you need confidentiality, use a JWE (JSON Web Encryption) token instead.

Can I decode a JWT without knowing the secret key?

Yes. Decoding the header and payload requires no key — they are just Base64URL-encoded JSON. This tool decodes them entirely in your browser without any server call. The key is only required to verify the signature, which proves the token was issued by a specific party and hasn't been tampered with.

How do I verify a JWT signature?

Signature verification must happen on your server, not in a client-side tool. For HMAC algorithms (HS256/HS384/HS512) you need the shared secret. For RSA/ECDSA algorithms (RS256/ES256 etc.) you need the issuer's public key, usually fetched from their JWKS endpoint at /.well-known/jwks.json. Use a trusted JWT library (jsonwebtoken for Node.js, PyJWT for Python, java-jwt for Java) rather than implementing verification manually.

What does 'EXPIRED' mean and can I still use the token?

An expired JWT has passed its 'exp' (expiration time) claim. A well-implemented server will reject it. You should not use expired tokens for authorization — request a new one using your refresh token or by re-authenticating. The expiry is deliberate: short-lived tokens limit the damage window if a token is stolen.

What is the difference between HS256, RS256, and ES256?

HS256 is symmetric (HMAC-SHA-256) — the same secret signs and verifies, so only parties you trust with the secret can verify tokens. RS256 is asymmetric (RSA) — a private key signs, a public key verifies, so you can publish the public key safely. ES256 is also asymmetric (ECDSA P-256) — same trust model as RS256 but with shorter signatures and keys, preferred for bandwidth-constrained use cases.

What does 'alg: none' mean and why is it dangerous?

A JWT with 'alg: none' carries no signature at all. Historically, some JWT libraries would accept these tokens as valid, allowing an attacker to forge arbitrary claims by crafting a token with no signature. Always configure your JWT library with an explicit allowlist of accepted algorithms (e.g. ['HS256'] or ['RS256']) and reject 'none' unconditionally.

Why does my JWT have three parts separated by dots?

The three parts are header, payload, and signature — each Base64URL-encoded. The header describes the token type and algorithm. The payload contains the claims. The signature covers 'base64url(header).base64url(payload)' and binds the two together cryptographically. Changing any character in the first two parts invalidates the signature.

Is it safe to paste a production JWT into this tool?

Yes — this tool runs entirely in your browser. The token is decoded with JavaScript locally and is never sent to any server. You can confirm this by checking the Network tab in your browser's DevTools; no outbound requests are made when you paste a token.

What is the 'aud' claim and why should I validate it?

The 'aud' (audience) claim names the intended recipient(s) of the token. If your API does not validate this claim, a token issued for a different service can be replayed against yours. For example, a token issued for 'service-a' could be accepted by 'service-b' if neither validates the audience. Always check that 'aud' matches your service identifier before trusting a token.

Where should I store JWTs in a browser application?

For most applications, an HttpOnly Secure SameSite=Strict cookie is safer than localStorage. Cookies with HttpOnly cannot be read by JavaScript, so an XSS attack cannot directly steal the token. localStorage is accessible to all scripts on the page. If your threat model requires defense-in-depth against XSS token theft, use HttpOnly cookies and pair them with CSRF protection.