JWT Tokens Explained: How to Read and Decode Them

JWT (JSON Web Token) tokens have become the standard for modern authentication and authorization in web applications. Despite their apparent complexity, understanding JWT tokens is essential for any developer working with APIs, microservices, or modern single-page applications. JWTs enable stateless authentication, eliminate the need for server-side session storage, and provide a secure, standardized way to transmit information between parties. This comprehensive guide demystifies JWT tokens and teaches you how to read, decode, and work with them effectively in your applications.

Ad space - Advertisement placement 1

What Is a JWT Token?

A JWT is a self-contained token that holds information about a user or application in a compact, URL-safe format. It's encoded and optionally signed and encrypted, making it secure for transmission between parties. Unlike traditional session tokens that require server-side storage, JWTs contain all necessary information within themselves. This makes them ideal for distributed systems where different servers shouldn't need to share session data.

JWTs are widely used in modern authentication flows, OAuth 2.0 implementations, and API security. They solve the problem of stateless authentication—the server doesn't need to remember sessions because all relevant information is contained in the token itself. This makes JWTs scalable and perfect for microservices architectures where multiple services need to verify the same user without shared session storage.

The Three Parts of a JWT Token

Every JWT consists of three parts separated by dots: header.payload.signature. Understanding each part is crucial for working with tokens effectively.

Part 1: The Header

The header contains metadata about the token, typically including the token type (JWT) and the signing algorithm used (HS256, RS256, etc.). The header is a JSON object encoded in Base64URL format. When decoded, a typical header looks like this:

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

The "alg" field specifies which algorithm was used to sign the token. Common algorithms include HS256 (HMAC SHA-256), RS256 (RSA SHA-256), and ES256 (ECDSA SHA-256). This tells the server how to verify the signature.

Part 2: The Payload

The payload contains the actual data or claims. Claims are statements about the user or application. The payload is also Base64URL encoded JSON. A typical payload looks like:

{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516242622 }

Standard claims include "sub" (subject, usually user ID), "iat" (issued at timestamp), and "exp" (expiration timestamp). You can add custom claims containing application-specific information. The payload is visible to anyone with the token—never store sensitive information like passwords here.

Part 3: The Signature

The signature proves the token hasn't been tampered with. It's created by encoding the header and payload, then signing them with a secret key or private key using the algorithm specified in the header. Only the server with the secret key can create or verify valid signatures. The signature ensures integrity—if someone modifies the payload, the signature becomes invalid.

Ad space - Advertisement placement 2

How to Decode a JWT Token

Using an Online JWT Decoder

The simplest way to decode and inspect a JWT is using an online tool like ToolPilot's JWT Decoder. Simply paste your token, and it immediately decodes all three parts into readable JSON. This is perfect for debugging and understanding what information a token contains. However, never use public online decoders for tokens containing sensitive information—the website operator could see your data.

Decoding Manually

You can decode a JWT manually by splitting it at the dots and Base64URL decoding each part. In JavaScript:

const token = "eyJhbGc..."; const [headerEncoded, payloadEncoded, signature] = token.split('.'); const header = JSON.parse(atob(headerEncoded)); const payload = JSON.parse(atob(payloadEncoded)); console.log(header); console.log(payload);

The key difference from standard Base64 is that JWT uses Base64URL encoding, replacing special characters (+/ with -_). Most programming languages provide libraries that handle this automatically.

Decoding in Your Application

In production applications, use language-specific libraries. Most frameworks include JWT support. For Node.js, the jsonwebtoken library is standard. Python developers use PyJWT. For Go, jwt-go is popular. These libraries handle both decoding and signature verification automatically. Always verify the signature when decoding—never trust a token just because you can read it.

Pro Tip: Always verify JWT signatures in your application. Decoding without verification proves nothing—anyone can create a token with any payload. Signature verification ensures the token came from a trusted source.

Understanding JWT Claims

Standard registered claims are defined by JWT specifications. "iss" (issuer) identifies who created the token. "sub" (subject) identifies the user. "aud" (audience) specifies intended recipients. "exp" (expiration time) is a timestamp when the token becomes invalid. "nbf" (not before) specifies when the token becomes valid. "iat" (issued at) shows when the token was created.

Custom claims allow you to include application-specific information. Common custom claims include user roles, permissions, email, and user ID. Be careful with custom claims—they're visible to anyone with the token and could expose information if the token is compromised.

JWT Security Best Practices

Always transmit JWTs over HTTPS to prevent interception. Include expiration times in your tokens to limit the window if a token is compromised. Use appropriate signing algorithms—RS256 is more secure than HS256 for distributed systems. Verify signatures on every token usage—never skip verification. Store tokens securely in your application, typically in secure HTTP-only cookies rather than localStorage which is vulnerable to XSS attacks.

Implement token refresh mechanisms where short-lived access tokens are paired with longer-lived refresh tokens. This allows users to stay logged in while limiting exposure from compromised access tokens. Never store sensitive information like passwords or payment details in JWT payloads.

Common JWT Use Cases

API authentication is the most common use case—clients send JWTs in Authorization headers. Single sign-on systems use JWTs to allow users to log in once across multiple applications. Microservices use JWTs to pass user context between services without sharing session storage. Mobile applications use JWTs because they're stateless and work well with REST APIs. Progressive web applications use JWTs for persistent authentication across page refreshes.

Decode Your JWT Tokens

Use ToolPilot's free JWT decoder to inspect and understand your tokens instantly.

Decode JWT Token
Disclaimer: Some links in this article may be affiliate links. We earn a small commission if you choose to use these services, at no cost to you. Our recommendations are based on product quality and value.

Frequently Asked Questions

Is a JWT token encrypted?
JWTs are encoded (Base64), not encrypted by default. The payload is readable to anyone with the token. Encryption is available through JWE (JSON Web Encryption) if needed, but standard JWTs with just signatures don't encrypt the payload. Never store sensitive passwords or payment details in JWT claims.
How long are JWT tokens valid?
Validity depends on the "exp" (expiration) claim set when creating the token. Common patterns include 15-minute expiration for access tokens paired with longer-lived refresh tokens. Access tokens for less secure contexts might expire in hours, while refresh tokens can last days or weeks.
Can JWT tokens be revoked?
Standard JWTs cannot be revoked until expiration. To enable revocation, maintain a blacklist or token database. Alternatively, use short expiration times and pair with refresh tokens, allowing you to deny refresh requests when revocation is needed. Some systems use token version numbers within claims.