Free Online JWT Debugger & Decoder
JWTs power authentication in modern APIs, but their Base64-encoded structure makes them opaque at a glance. Dokall decodes the header and payload, validates structure, and helps you encode or verify tokens during development.
Debug OAuth flows, inspect session tokens, and test signature verification - all in your browser. Never paste production secrets on untrusted sites; Dokall processes tokens client-side.
How JWT Authentication Works
When a user logs in, the server creates a JWT containing the user's identity and permissions, signs it with a secret key, and returns it. On every subsequent request, the client sends the JWT - typically in the Authorization header as Bearer <token>. The server verifies the signature without querying a session store.
This stateless design means any server that holds the signing key can validate the token independently. That makes JWTs popular in microservice architectures, single-page applications, and mobile APIs where the authentication server and the resource server may be different machines.
JWT Structure: Header, Payload, Signature
A JWT is three Base64url-encoded JSON objects separated by dots: header.payload.signature.
The header declares the token type (always JWT) and the signing algorithm, for example {"alg": "HS256", "typ": "JWT"}. The payload carries claims - key-value pairs that describe the user or session. Claims can be registered (defined by the spec), public (custom but collision-resistant), or private (agreed between parties). The signature is produced by signing the encoded header and payload with a secret or private key. Anyone with the corresponding key can verify the token has not been altered.
When you paste a token into this debugger, it splits on the dots, decodes each part, and displays the JSON. No secret is needed to read the header and payload - only to verify the signature.
Signature Algorithms: HS256 vs RS256 vs ES256
HS256 (HMAC + SHA-256) is a symmetric algorithm. The same secret key signs and verifies. It is fast and simple, but every service that needs to verify tokens must know the secret. If one service is compromised, the key is exposed.
RS256 (RSA + SHA-256) is asymmetric. A private key signs the token and a public key verifies it. Only the auth server needs the private key - downstream services use the public key, which is safe to distribute. RS256 keys are larger (2048+ bits) and signing is slower, but verification is fast.
ES256 (ECDSA + P-256) is also asymmetric but uses elliptic curve cryptography. Keys are much smaller than RSA (256-bit vs 2048-bit) and operations are faster, making ES256 a good default for new systems. Most JWT libraries and cloud providers support it.
Choose HS256 for simple single-server setups. Choose RS256 or ES256 when multiple services verify tokens or when you publish a JWKS endpoint.
Standard JWT Claims Reference
The JWT specification (RFC 7519) defines seven registered claims. None are mandatory, but using them consistently helps interoperability.
iss (issuer) identifies who created and signed the token, typically a URL like https://auth.example.com. sub (subject) identifies the principal - usually a user ID. aud (audience) specifies the intended recipient, often the API domain. exp (expiration time) is a Unix timestamp after which the token must be rejected. iat (issued at) records when the token was created. nbf (not before) prevents the token from being used before a specific time. jti (JWT ID) is a unique identifier useful for one-time tokens or revocation lists.
Beyond registered claims, you can add any custom data your application needs - roles, permissions, tenant IDs, email addresses. Just keep the payload small. Every byte increases the size of every HTTP request that carries the token.
JWT vs Session-Based Authentication
Session-based auth stores state on the server. When a user logs in, the server creates a session record (in memory, a database, or Redis), assigns a session ID, and sends it to the client as a cookie. Each request includes the cookie, and the server looks up the session. Revoking access is instant - delete the session.
JWT auth is stateless. The token itself contains all the information the server needs. No database lookup on each request, no shared session store across servers. The downside: you cannot truly revoke a JWT before it expires without maintaining a blocklist, which partially negates the stateless benefit.
Sessions are simpler and better when you need instant revocation (banking, admin panels). JWTs are better for distributed systems, cross-domain APIs, and mobile clients where cookies are inconvenient. Many production systems combine both - short-lived JWTs for API access with a server-side refresh token that can be revoked.
Common JWT Errors and How to Fix Them
"Token expired" means the current time has passed the exp claim. Check whether your server clock is synchronized (NTP drift is a common cause in containers). If the token lifetime is too short, increase it or implement a refresh token flow.
"Invalid signature" means the verification key does not match the signing key. This often happens when deploying with environment-specific secrets and the wrong secret is loaded, when rotating keys without updating all services, or when copying a token between environments.
"Token not yet valid" triggers when the current time is before the nbf claim. This is usually a clock skew issue between the issuing server and the verifying server. Most JWT libraries accept a small clock tolerance (typically 30-60 seconds).
"Malformed JWT" means the token does not have three dot-separated parts or a part is not valid Base64url. Check for accidental whitespace, line breaks, or truncation when copying tokens from logs or emails.
JWT Security Best Practices
The payload is encoded, not encrypted. Anyone who intercepts a JWT can read its claims. Never put passwords, credit card numbers, or other secrets in the payload.
Use short expiration times - 15 minutes for access tokens is a common choice. Pair them with longer-lived refresh tokens stored securely on the server. This limits the damage window if a token is stolen.
For HS256, your secret should be at least 256 bits of cryptographic randomness. A short passphrase is vulnerable to brute-force attacks. Use a key generator to create proper secrets.
Always validate the alg claim server-side. The "algorithm confusion" attack tricks a server into treating an RS256 token as HS256, using the public key as the HMAC secret. Modern libraries protect against this, but explicit algorithm configuration is still recommended.
Prefer httpOnly, Secure, SameSite cookies for storing JWTs in browsers. localStorage is accessible to any JavaScript on the page, making it vulnerable to XSS attacks. Cookies with proper flags are immune to XSS token theft.