← Software Engineering Studio
RFC 7519 — JSON Web Token

JWT Token Inspector

Decode and inspect JSON Web Tokens. View the header algorithm, all payload claims, and expiry status. All decoding happens in your browser — no data is sent anywhere.

🔴 Expired
🔐 HS256
Issued 729d 18h ago
🔴 Header
alg"HS256"
HMAC SHA-256 — symmetric, shared secret. Simple but secret must be shared.
typ"JWT"
🟣 Signature
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
HMAC signature — verified with a shared secret. This tool cannot verify the signature (the secret is not known).
🔵 Payload — 10 claims
sub"user_123456"
Subject — unique identifier for the token subject (usually user ID)
iss"https://auth.example.com"
Issuer — identifies the principal that issued the JWT
aud"https://api.example.com"
Audience — recipients this JWT is intended for
iat1719230000Mon, 24 Jun 2024 11:53:20 GMT
Issued At — unix timestamp when the JWT was issued
exp1719233600Mon, 24 Jun 2024 12:53:20 GMTEXPIRED
Expiration Time — unix timestamp after which the JWT must not be accepted
nbf1719230000Mon, 24 Jun 2024 11:53:20 GMT
Not Before — unix timestamp before which the JWT must not be accepted
jti"abcdef123456"
JWT ID — unique identifier for this token (prevents replay attacks)
permissions["read:users", "write:orders"]
Custom claim: list of permissions granted
role"admin"
Custom claim: user role
email"alice@example.com"
Email address of the user
Header JSON
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload JSON
{
  "sub": "user_123456",
  "iss": "https://auth.example.com",
  "aud": "https://api.example.com",
  "iat": 1719230000,
  "exp": 1719233600,
  "nbf": 1719230000,
  "jti": "abcdef123456",
  "permissions": [
    "read:users",
    "write:orders"
  ],
  "role": "admin",
  "email": "alice@example.com"
}

About the JWT Token Inspector

This tool decodes JSON Web Tokens (JWT) defined in RFC 7519. Paste any JWT to instantly view the decoded header (algorithm and type), all payload claims with human-readable timestamps and expiry status, and the raw base64url-encoded signature. All decoding happens entirely in your browser — no token data is ever sent to a server.

JWT structure: three base64url-encoded parts

A JWT consists of three dot-separated parts: HEADER.PAYLOAD.SIGNATURE. Each part is base64url-encoded (URL-safe base64 — uses - and _ instead of + and /). The header is a JSON object declaring the algorithm (alg: HS256, RS256, ES256, etc.) and token type (typ: JWT). The payload is a JSON object containing claims — registered claims like sub (subject), iss (issuer), exp (expiration), iat (issued at), nbf (not before), jti (JWT ID), and custom claims specific to your application. The signature is created by the issuer using the header + payload + a secret or private key — it proves the token was issued by a trusted party and has not been tampered with.

Time claims: exp, iat, nbf

exp (Expiration Time): The token MUST NOT be accepted after this time. Value is Unix epoch seconds (integer). This tool highlights expired tokens in red. Short-lived access tokens (15 minutes to 1 hour) reduce the window of exposure if stolen. Long-lived tokens (days/weeks) should only be used for refresh tokens stored securely.

iat (Issued At): When the token was created. Useful for detecting tokens issued in the far past or future (clock skew attack).

nbf (Not Before): The token MUST NOT be accepted before this time. Used when a token is issued in advance for future use — for example, a scheduled access grant.

All three are in Unix epoch SECONDS (not milliseconds). A common bug is storing JWT exp as milliseconds (JavaScript Date.now() returns ms) — this creates tokens that expire 1000× sooner or appear far in the future.

Algorithm security: HS256 vs RS256 vs ES256

HS256 (HMAC-SHA256): Uses a single shared secret for both signing and verification. Simple to implement but the secret must be shared between the token issuer and every service that verifies tokens. If any service is compromised, the secret is exposed and attackers can forge any token. Not suitable for distributed microservices. RS256 (RSA-SHA256): Asymmetric — the issuer signs with a private key, and any service verifies with the public key. The private key never leaves the auth server, making it safe to distribute the public key to all microservices. This is the recommended algorithm for production APIs. ES256 (ECDSA-SHA256): Asymmetric like RS256 but uses elliptic curve cryptography. Smaller key sizes (256-bit vs 2048-bit RSA) with equivalent security. Preferred in performance-sensitive environments. NEVER use alg: none in production — it disables signature verification entirely, allowing anyone to forge a valid token.

Security considerations

Token storage: Store JWTs in httpOnly cookies (not localStorage) for web applications — localStorage is accessible via JavaScript and vulnerable to XSS. httpOnly cookies are invisible to JavaScript and immune to XSS-based theft (though CSRF must be mitigated with SameSite=Strict or CSRF tokens). Token scope: Access tokens should carry the minimum required claims. Never put passwords, secrets, or sensitive PII in JWT payloads — they are base64-encoded, not encrypted, and readable by anyone. Use the aud (audience) claim to restrict which services can accept a token. Verification in code: always verify the signature and check exp before trusting any claim. JWT libraries like jsonwebtoken (Node.js), PyJWT (Python), and java-jwt do this automatically — never manually decode without verifying.

Frequently asked questions

Is the JWT payload encrypted?

No — a standard JWT (JWS, JSON Web Signature) is signed but NOT encrypted. The header and payload are base64url-encoded, which is easily reversed by anyone who has the token. Never put sensitive data (passwords, social security numbers, credit card numbers, private keys) in a JWT payload. If you need encrypted tokens, use JWE (JSON Web Encryption), which is a different format defined in RFC 7516.

Why can this tool decode any JWT without a secret?

Because base64url decoding requires no key — the header and payload are just base64url-encoded JSON. The signature is the only part that requires a key to verify. This tool decodes (base64url reverse) but does not verify. Anyone who obtains a JWT can read its claims. This is why JWTs must be kept confidential (use HTTPS, store in httpOnly cookies) and must not contain sensitive data.

How do I verify a JWT in my application?

Use a JWT library, never implement verification manually. Node.js: jsonwebtoken — jwt.verify(token, secretOrPublicKey, {algorithms: ["RS256"]}). Python: PyJWT — jwt.decode(token, public_key, algorithms=["RS256"]). Java: java-jwt (Auth0) or jjwt. Always specify the allowed algorithms explicitly — some older libraries had the "none" algorithm vulnerability where setting alg to "none" in the header would bypass verification. Specify algorithms: ["RS256"] (or whatever you use) so the library rejects any other algorithm.

What is the difference between access tokens and refresh tokens?

Access tokens are short-lived JWTs (typically 15 min to 1 hour) sent with every API request to prove identity. Short lifetimes minimize the damage if stolen. Refresh tokens are long-lived opaque tokens (days to weeks) stored securely (httpOnly cookie or secure storage) and used to obtain new access tokens when the current one expires — they are exchanged at the auth server, never sent to resource APIs. The user's session feels continuous (they don't need to log in again) but the access token exposure window is kept small.

What does the jti (JWT ID) claim do?

The jti claim provides a unique identifier for each JWT instance. It's used to prevent replay attacks: if an attacker captures a valid JWT, they could resend it to the API (within its exp window). By maintaining a server-side blocklist of used jti values, the server can reject a token that has already been used — this is especially important for single-use tokens like password reset links. jti is typically a UUID or a random 128-bit value generated at token creation.

Related tools & guides

Regex TesterAlgorithm Complexity ReferenceAPI DesignerWeb Security — OWASP Top 10