JWT Token Encode / Decode



How to Use the JWT Token Encode / Decode

1

Paste your JWT token to decode

Paste your JWT token to decode.

2

Or enter header and payload to encode

Or enter header and payload to encode.

3

View decoded parts and verify the signature

View decoded parts and verify the signature.

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

JSON Web Tokens have quietly become the backbone of modern authentication. Whether you're building a REST API that authenticates mobile clients, implementing single sign-on across multiple services, or debugging why a certain endpoint keeps returning 401 errors — you're almost certainly dealing with JWTs. They sit in the Authorization: Bearer header of every authenticated API call, they're what gets stored after a user logs in through OAuth, and they're the token format that services like Auth0, Firebase Auth, and AWS Cognito issue by default.

This tool does two things: decode any JWT you paste into it so you can read its header, payload, and verify what claims it carries — and encode a custom JWT from a JSON payload and signing secret. Both operations run entirely in your browser, which is important when you're working with tokens from live systems. Nothing gets sent to any server.

A quick decode can save you thirty minutes of guesswork. Is the token expired? Does it carry the right user ID? Was it issued by the service you expected? Is the iss claim pointing at the right authority? These are questions you can answer in seconds with a decoder rather than adding temporary log statements to your application.

The Three-Part JWT Structure — Header, Payload, Signature

Every JWT follows the same anatomy: three base64url-encoded segments separated by dots — xxxxx.yyyyy.zzzzz. Understanding what lives in each segment is the foundation of working with JWTs in any capacity.

The Header is a JSON object containing exactly two fields: typ, which is always "JWT", and alg, which names the signing algorithm. The most common algorithms you'll encounter are HS256 (HMAC with SHA-256 — symmetric, meaning the same secret both signs and verifies), RS256 (RSA with SHA-256 — asymmetric, using a private key to sign and a public key to verify), and ES256 (ECDSA with P-256 curve — also asymmetric, with smaller key sizes than RSA). The algorithm field matters enormously: it tells the verifier what to expect, and accepting the wrong algorithm is the root cause of several well-known JWT attacks.

The Payload carries the claims — structured data about the authenticated subject and the token itself. The spec defines several registered claims with well-established semantics: sub (the subject, typically a user or service ID), iss (issuer — who created this token), aud (audience — which service this token is intended for), exp (expiration — a Unix timestamp after which the token should be rejected), iat (issued at), nbf (not before — earliest time the token is valid), and jti (a unique token ID, useful for revocation lists). Beyond these, you'll often see custom claims like role, permissions, or org_id that carry application-specific data.

The Signature ties the whole thing together. It's computed by taking the encoded header and payload, concatenating them with a period, and signing the result with the algorithm and key specified in the header. This is what lets a receiving server verify two things: that the token was created by someone who holds the signing key (authenticity), and that nobody modified the header or payload after it was signed (integrity). Change a single character in the payload and the signature becomes invalid.

The point that trips up almost every developer new to JWTs: base64url encoding is not encryption. It's a reversible text encoding. Anyone with the token can decode the header and payload — no key required. Paste any JWT into the decoder on this page and you'll see the claims in plaintext immediately. The signature verifies authenticity and integrity, it does not provide confidentiality. Treat JWT payloads as public information and never put secrets like passwords, API keys, or payment details inside one.

How JWT Authentication Flows Actually Work

A typical JWT authentication sequence: the client sends credentials (username and password, an OAuth authorization code, a social login token) to the server's authentication endpoint. The server validates the credentials against its user store. If valid, the server constructs a JWT payload containing the user's ID, relevant roles or permissions, an issuer identifier, and an expiration time — then signs it and returns it to the client. From that point on, the client includes the token in the Authorization: Bearer <token> header with every API request. The receiving server decodes the token, verifies the signature, checks that the token hasn't expired, and reads the claims — all without hitting the database. That stateless verification is the fundamental advantage of JWTs over server-side session stores.

The inherent trade-off is revocation. Because the server never stores a registry of issued tokens, revoking a specific token before its natural expiration requires maintaining a blocklist of revoked jti values — which reintroduces state into a stateless system. The practical pattern that most teams settle on: very short-lived access tokens (15–60 minutes) paired with longer-lived refresh tokens (days or weeks). When the access token expires, the client uses the refresh token to obtain a fresh one. If a user logs out, is deactivated, or a security incident occurs, invalidate the refresh token — no new access tokens will be issued after the current one expires.

A common mistake: putting too much data into the JWT payload. Remember that every token is transmitted with every request, and the payload is base64url-encoded (not compressed). A token carrying a large array of permissions or a list of assigned projects adds measurable overhead to every single API call. Keep payloads lean — store references (like role IDs) rather than full objects, and fetch detailed data from the server when needed.

HS256 vs. RS256 — Choosing the Right Signing Algorithm

HS256 (HMAC-SHA256) uses a single shared secret for both signing and verification. Any service that needs to verify tokens must also have access to the signing secret. This is straightforward for a monolithic application where one server both issues and validates tokens — or a small system with two or three services that can securely share a secret through environment variables or a secrets manager. The simplicity is its strength.

RS256 (RSA-SHA256) uses asymmetric key pairs. The private key stays on the issuing service; the public key can be freely distributed to any service that needs to verify tokens. In a microservices architecture with a dedicated auth service and dozens of downstream services, RS256 means each downstream service verifies tokens independently using the published public key without ever needing access to the signing secret. Services like Auth0 and AWS Cognito use RS256 (or the equivalent ECDSA variant) precisely because the public key distribution model scales cleanly.

A practical decision rule: if your system has one authority that issues tokens and potentially many services that verify them, use RS256 or ES256. If a single service handles both issuance and verification, HS256 is simpler and performs marginally faster.

Security Vulnerabilities Every Developer Should Know

The alg: none attack: Some early JWT libraries accepted tokens where the header specified "alg": "none" — meaning "no signature required." An attacker could craft a token with any claims they wanted, set the algorithm to none, and the library would accept it as valid. This vulnerability was disclosed in 2015 and affected several major JWT implementations. Modern libraries reject alg: none by default, but if you've written your own JWT verification logic or are using an older, unmaintained library, this remains a real risk. Always use a maintained library and explicitly whitelist accepted algorithms.

Algorithm confusion: Suppose your server accepts both RS256 and HS256 tokens. An attacker takes an RS256-signed token, changes the header to claim "alg": "HS256", and signs it using your server's public key (which is, by definition, publicly known). If the server naively reads the alg field and switches to HMAC verification using the public key as the secret, the forged token passes verification. The defense: always specify the expected algorithm on the server side — never derive it from the token itself.

Missing claim validation: Verifying the signature is necessary but not sufficient. Your server must also independently validate the exp claim (reject expired tokens), the iss claim (confirm the expected issuer), and the aud claim (confirm the token is intended for your service). Skipping any of these — especially aud in a multi-service system — creates a window for token replay across services. A token issued for Service A should be rejected by Service B, even if Service B can verify the signature.

Weak signing secrets: For HS256, the security of every token depends on the strength and secrecy of the signing key. A common mistake in development is using a short or predictable secret like "secret" or "changeme" and forgetting to rotate it when moving to production. Signing keys should be cryptographically random, at least 256 bits long for HS256, and stored in a dedicated secrets manager — never committed to source code or hardcoded in configuration files.

Frequently Asked Questions About JWT

No — and this surprises many developers. The payload is base64url-encoded, not encrypted. Base64url is a reversible encoding anyone can decode by hand in seconds. The signature proves the token was issued by a trusted party and hasn't been tampered with, but it provides zero confidentiality. Anyone who intercepts a JWT — in a log file, a browser's network tab, a URL parameter — can read its full payload. Never store passwords, credit card numbers, social security numbers, or any other sensitive data in a standard JWT. If you need encrypted payloads, use JWE (JSON Web Encryption), which encrypts the payload end-to-end.
HS256 uses a single symmetric secret — the same key signs and verifies tokens. Every service that needs to verify tokens must have access to that secret. RS256 uses an asymmetric key pair: the private key signs tokens, and the public key verifies them. The public key can be shared openly (often published at a /.well-known/jwks.json endpoint), so any number of services can verify tokens without ever possessing the signing key. RS256 is strongly preferred in multi-service architectures and is the default for most third-party identity providers. ES256 provides similar asymmetric guarantees with smaller keys and faster operations on modern hardware.
True revocation of a stateless token requires introducing server-side state — which is the fundamental trade-off. Common approaches: maintain a blocklist of revoked jti values (requires a fast lookup store like Redis); use very short access token lifetimes (15 minutes) so the window of exposure is small, paired with a revocable refresh token; rotate the signing secret periodically (revokes all outstanding tokens at once, which is effective for emergency scenarios); or fall back to opaque reference tokens for high-security endpoints where you need instant revocation. Most production systems combine short-lived JWTs with a refresh token rotation scheme.
The two main options are localStorage and HttpOnly cookies, each with a different threat model. localStorage is simple but fully accessible to JavaScript — any XSS vulnerability on your site can exfiltrate the token. HttpOnly cookies are inaccessible to JavaScript and are the generally recommended storage mechanism for browser-based applications, though they require CSRF protection (same-site cookie attributes, CSRF tokens, or both). For mobile apps, use platform-specific secure storage: iOS Keychain, Android Keystore, or React Native's react-native-keychain. Never store JWTs in sessionStorage (vulnerable to XSS, with none of the CSRF protection benefits of cookies) or in regular non-HttpOnly cookies (accessible to JavaScript, defeating the purpose).
In early JWT implementations, a token with "alg": "none" in the header caused the library to skip signature verification entirely. An attacker could set any claims they wanted, set the algorithm to "none," and the library would accept the token as valid — effectively forging authentication credentials out of thin air. This vulnerability affected the Java jwt-auth, node-jsonwebtoken, and several other libraries before it was patched. It remains a risk in custom JWT handling code and abandoned libraries. The defense: use a well-maintained, actively updated JWT library, explicitly specify the expected algorithm(s) on the server, and never accept whatever algorithm the token header claims.
A standard JWT (technically a JWS — JSON Web Signature) has a signed but readable payload — anyone can decode and read the claims. JWE (JSON Web Encryption) encrypts the payload so that only the intended recipient can read it. JWE tokens have five base64url-encoded parts instead of three and use encryption keys (either symmetric or asymmetric) in addition to signing. Use JWE when the token must carry sensitive data that intermediate parties — CDN edge servers, logging infrastructure, analytics proxies — should be able to route but not inspect. For most authentication use cases, JWS with a minimal, non-sensitive payload is the right choice.
Short-lived access tokens — anywhere from 5 minutes to 1 hour — paired with longer-lived refresh tokens is the recommended pattern. The access token's job is to authenticate a request; its short lifetime limits the damage if it's intercepted. The refresh token's job is to obtain new access tokens and lives long enough to provide a good user experience (days to weeks). For internal APIs with trusted consumers, longer expiration may be acceptable, but you should still set exp — never issue a token with no expiration at all. The exp claim should always be present, and your verification logic should always check it.
Technically yes, but it's rarely the best approach for traditional web sessions. Server-side sessions give you instant revocation, stored session data, and no token size concerns. JWTs shine in stateless, cross-service authentication — mobile apps, single-page applications communicating with APIs, microservices that need to verify identity without shared databases. If you're building a standard server-rendered web app, a session cookie with server-side storage is typically simpler, more secure, and easier to debug. Use JWTs where their statelessness provides a genuine architectural advantage, not as a default replacement for sessions.