JWT Token Encode / Decode



JWT Encoder & Decoder — Inspect, Decode, and Create JSON Web Tokens Online

JSON Web Tokens (JWT) have become the dominant format for transmitting authentication and authorization data in modern web applications, APIs, and microservices. If you've built or consumed a REST API in the last several years, you've almost certainly worked with JWTs — they're the token inside the Authorization: Bearer header, the credential your mobile app stores after login, the access token issued by OAuth providers. This tool gives you two capabilities: decode any existing JWT to read its header and payload in plain JSON, and encode a new JWT by providing a payload and signing secret. Both operations run entirely in your browser — nothing is transmitted to any server, which matters when working with tokens from live authentication systems.

For developers, being able to quickly decode a JWT during debugging — to check what claims are present, verify the expiration time, inspect the issuer, or confirm the user ID — saves time that would otherwise be spent adding log statements or parsing the token manually. Being able to encode a test token with custom claims is equally useful when building and testing protected API endpoints.

The Three-Part JWT Structure Explained

Every JWT has the same structure: three base64url-encoded strings separated by periods — header.payload.signature. Understanding what each part contains is the foundation of working with JWTs confidently.

Header: A JSON object with two fields — typ (token type, always "JWT") and alg (the signing algorithm). Common algorithms are HS256 (HMAC-SHA256, symmetric — uses a shared secret), RS256 (RSA-SHA256, asymmetric — uses a private key to sign, public key to verify), and ES256 (ECDSA, asymmetric). The algorithm field is critical: your server must explicitly accept only expected algorithms and never accept "none".

Payload: A JSON object containing the claims — statements about the subject (typically the authenticated user) and any additional application data. The JWT specification defines registered claim names with standard meanings: sub (subject, usually a user ID), iss (issuer, who created the token), aud (audience, who the token is for), exp (expiration time, Unix timestamp), iat (issued at), nbf (not before), and jti (JWT ID, unique token identifier). Beyond these, you can add any custom claims your application needs — roles, permissions, user metadata.

Signature: Computed by taking the base64url-encoded header, a period, the base64url-encoded payload, and signing the combined string with the algorithm and secret specified in the header. The signature is what allows a server to verify that the token was issued by a trusted source and has not been modified in transit. If any character in the header or payload changes, the signature no longer matches.

The critical point that every developer working with JWTs must understand: base64url encoding is not encryption. The header and payload can be decoded by anyone — there is no key required. Paste any JWT into the decoder on this page and you'll see the claims in plain JSON immediately. The signature only verifies authenticity and integrity; it does not provide confidentiality. Never put passwords, payment details, private keys, or other sensitive data in a standard JWT payload.

How JWT Authentication Works in Practice

The standard JWT authentication flow: a user submits their credentials (username/password, OAuth code, etc.). The server validates them. The server generates a JWT with the user's ID, roles, and an expiration time, signs it with its secret or private key, and returns it to the client. The client stores the token and sends it with every subsequent request in the Authorization: Bearer <token> header. The server receives the request, validates the JWT signature, checks the expiration, and reads the claims — all without any database lookup. This stateless verification is JWT's core advantage over server-side session storage.

The trade-off is revocation: because the server doesn't store issued tokens, revoking a specific token before it expires requires maintaining a blocklist of revoked token IDs (jti values) — which reintroduces server state. The common mitigation is short-lived access tokens (15–60 minutes) paired with a longer-lived refresh token. When the access token expires, the client uses the refresh token to obtain a new one. If a user logs out or is deactivated, the refresh token is invalidated, and no new access tokens will be issued after the current access token expires.

HS256 vs. RS256 — Choosing a Signing Algorithm

HS256 (HMAC-SHA256) uses a single symmetric secret — the same key is used to sign tokens and to verify them. This is simpler to implement and perfectly appropriate when a single service both issues and verifies tokens. The risk is key distribution: any service that needs to verify tokens also needs the secret, which means the secret must be securely shared across services.

RS256 (RSA-SHA256) uses asymmetric key pairs — a private key signs tokens, and a public key verifies them. The issuing service keeps the private key secret, but the public key can be freely distributed (or published at a .well-known/jwks.json endpoint). This means any service in a microservices architecture can verify tokens independently without needing access to the signing secret. RS256 is the preferred algorithm for multi-service systems and public identity providers. ES256 (ECDSA) provides similar asymmetric properties with smaller key sizes.

Critical JWT Security Mistakes to Avoid

The "alg: none" vulnerability: Early JWT libraries would accept tokens with the algorithm set to "none" and no signature — effectively unsigned tokens that any attacker could forge by setting any claims they wanted. Always configure your JWT library to reject alg: none and to only accept explicitly whitelisted algorithms.

Algorithm confusion attacks: Some libraries that accept both HS256 and RS256 are vulnerable to an attacker switching a token's algorithm from RS256 to HS256 and signing it with the server's public key (which is known). The server then validates the HS256 signature using the public key as the HMAC secret and accepts the forged token. Mitigate by explicitly specifying the expected algorithm, never inferring it from the token itself.

Missing claim validation: Verifying the signature is necessary but not sufficient. Your server must also validate exp (reject expired tokens), iss (verify the expected issuer), and aud (verify the token is intended for your service). Skipping any of these creates security gaps even with a valid signature.

Frequently Asked Questions About JWT

No, the payload is not private by default. It is base64url-encoded, which is a reversible encoding anyone can decode — it is not encryption. Anyone who intercepts or is given a JWT can decode and read the header and payload. The signature only proves the token was issued by a trusted party and hasn't been modified. Never put passwords, credit card numbers, or other sensitive data in a standard JWT payload.
HS256 (HMAC-SHA256) uses a single shared secret for both signing and verification — whoever has the secret can create and verify tokens. RS256 (RSA-SHA256) uses a private key to sign and a public key to verify. With RS256, the issuer keeps the private key secret but publishes the public key — any party can verify tokens without being able to create new ones. RS256 is preferred in multi-service architectures where multiple services need to verify tokens but only one should issue them.
True revocation requires server-side state, which is the trade-off of stateless JWT authentication. Common approaches: maintain a blocklist of revoked jti values (fast lookup, but requires storage); use very short expiration times (15 minutes) with a separate refresh token flow; rotate the signing secret (revokes all tokens at once, useful for security incidents); or use an opaque token that references a server-side session for high-security use cases where revocation is critical.
The two main options are localStorage and HttpOnly cookies. localStorage is easy to use but exposes the token to JavaScript — any XSS vulnerability on your site can steal it. HttpOnly cookies are inaccessible to JavaScript and are the recommended storage for JWTs in browser-based applications, though they require CSRF protection. For mobile apps, secure storage APIs (iOS Keychain, Android Keystore) are appropriate. Never store JWTs in sessionStorage or as regular (non-HttpOnly) cookies.
Early JWT libraries had a critical vulnerability where setting "alg": "none" in the header caused the library to skip signature verification entirely — an attacker could forge any token by setting the algorithm to "none" and removing the signature. A correctly implemented JWT library rejects tokens with alg: none unless explicitly configured to accept them. Always use a well-maintained JWT library and explicitly specify the expected algorithm when verifying tokens, never accepting whatever the token header claims.
A standard JWT (technically a JWS — JSON Web Signature) has a signed but readable payload. JWE (JSON Web Encryption) encrypts the payload so only the intended recipient can read it. JWE tokens have five parts instead of three and use asymmetric or symmetric encryption keys. Use JWE when the payload contains sensitive data that must not be readable by intermediate parties — such as when passing tokens between services where some intermediaries should be able to route the token but not read its contents.
Short-lived access tokens (15 minutes to 1 hour) combined with longer-lived refresh tokens (days to weeks) is the recommended pattern. Short access tokens limit the damage window if a token is stolen — an attacker can only use it for the remaining lifetime. Refresh tokens are used to obtain new access tokens when they expire and can be revoked server-side. For low-risk internal APIs, longer expiration times may be acceptable. Never issue access tokens with no expiration (exp claim should always be set).