By AndyPublished

What is a JWT? JSON Web Tokens Explained

A JSON Web Token (JWT) is a compact, self-contained token format defined in RFC 7519. It lets two parties securely exchange claims, statements about a subject such as a user ID, role, or session scope, in a format that is both URL-safe and cryptographically verifiable. JWTs are the dominant token format in modern authentication and authorization systems.

The Problem JWTs Solve

Traditional web sessions store user state on the server. When a user logs in, the server creates a session record, assigns it a random ID, and sends that ID to the browser as a cookie. On every subsequent request, the server looks up the session ID to find the user's identity and permissions.

This model works well for single-server applications, but it creates problems at scale. If you run ten API servers behind a load balancer, each server needs access to the same session store — typically a shared database or Redis cluster. Every API call incurs a session lookup, adding latency and creating a single point of failure.

JWTs take a different approach: the token itself carries all the information the server needs to authenticate and authorize a request. The server doesn't need to look anything up. Instead, it verifies the token's cryptographic signature and reads the claims directly from the payload. This makes JWTs well-suited for distributed systems, microservices, and multi-region APIs.

JWT Anatomy: Three Parts

A JWT looks like three Base64url-encoded strings separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJ1c2VyXzEyMyIsIm5hbWUiOiJKYW5lIERldiIsImlhdCI6MTcxNjQ3NzM2MSwiZXhwIjoxNzE2NDgwOTYxfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1. Header

The header identifies the token type and the cryptographic algorithm used to sign it. Decoded, it becomes a JSON object like:

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

The alg field is critical for verification. Common values include HS256 (HMAC-SHA256 with a shared secret), RS256 (RSA-SHA256 with a public/private key pair), and ES256 (ECDSA-SHA256).

2. Payload

The payload contains the token's claims. A typical payload looks like:

{
  "sub": "user_123",
  "name": "Jane Developer",
  "iat": 1716477361,
  "exp": 1716480961,
  "roles": ["editor"]
}

Claims are divided into three categories: registered claims defined by RFC 7519 (like sub, exp, iss),public claims registered with IANA, and private claims defined by the application. The payload is Base64url-encoded, not encrypted, anyone with the token can read it.

3. Signature

The signature is computed over the concatenated header and payload using the signing key. It makes the token tamper-evident: change a single byte in the header or payload and the signature will no longer match. Verifying the signature requires either the shared secret (for HMAC algorithms) or the issuer's public key (for RSA/ECDSA algorithms).

How JWTs Are Issued

Understanding the issuance flow makes the security model clear. Here is the typical sequence for an API protected by JWT authentication:

1. User submits credentials (username + password) to the auth server.

2. Auth server verifies credentials against the user store.

3. Auth server builds the JWT payload:
   {
     "sub": "user_123",
     "iss": "https://auth.example.com/",
     "aud": "https://api.example.com",
     "iat": 1716477361,
     "exp": 1716480961,
     "roles": ["editor"]
   }

4. Auth server signs the token:
   token = base64url(header) + "." + base64url(payload) + "." + sign(...)

5. Auth server returns the token to the client.

6. Client sends the token on every API request:
   Authorization: Bearer eyJhbGci...

7. API server verifies the signature, checks exp/iss/aud,
   then reads the claims, no database lookup required.

The key insight is step 7: the API server needs only the signing key (or public key) to validate any token. It does not need a connection to the auth server or a session store on the hot path. This is what makes JWTs efficient at scale.

How JWTs Are Used in Practice

The most common use cases for JWTs are:

  • ·API authentication: After login, the auth server issues a JWT access token. The client sends this token in the Authorization: Bearer <token> header on every API request. The API server verifies the token locally without database lookups.
  • ·OAuth 2.0 and OpenID Connect: Modern identity providers (Auth0, Okta, AWS Cognito, Google) issue JWTs as access tokens and ID tokens. The ID token in OIDC is always a JWT and carries the authenticated user's identity claims.
  • ·Microservices authentication: A JWT issued by a central auth service can be verified by any downstream microservice that trusts the issuer's public key, enabling stateless authentication across service boundaries.
  • ·Single Sign-On (SSO): JWTs enable a user authenticated on one domain to access resources on another domain, since the token itself carries the identity proof.

JWT vs Session Tokens: When to Choose Which

JWTs and server-side sessions both solve the authentication persistence problem, but they have different tradeoffs. Choosing the wrong approach for your architecture creates unnecessary complexity or security risk.

PropertyJWTSession token
State storageClient (self-contained)Server (database / Redis)
VerificationCryptographic (no DB lookup)Database lookup per request
Horizontal scalingEasy (no shared state)Requires shared session store
RevocationHard (must expire or blocklist)Easy (delete session record)
Token sizeLarger (200–1000 bytes)Small (16–32 byte random ID)
Multi-service / SSONatural fitRequires centralised session store
Security on compromiseWindow = remaining token lifetimeRevoke immediately

Choose JWTs when: you have multiple independent services that need to verify tokens, you are building a public API consumed by mobile or third-party clients, or you need cross-domain SSO without a central session store.

Choose sessions when: you need immediate revocation (financial transactions, admin panels, high-security operations), your application is a single server, or you store sensitive per-request state that shouldn't travel in every token.

Many production systems use a hybrid approach: short-lived JWTs (5–15 minutes) for stateless API access, paired with a long-lived server-side refresh token (days to weeks). The JWT provides performance; the refresh token provides revocability.

Benefits of JWTs

  • ·Stateless: Servers don't need a session store. Any server with the signing key can verify any token, enabling horizontal scaling without shared state.
  • ·Self-contained: The token carries all necessary claims. No database lookup needed on the hot path, reducing latency and infrastructure complexity.
  • ·Cross-domain and cross-service: JWTs are URL-safe and work across HTTP headers, cookies, and POST bodies. They can be verified by any service that trusts the issuer's key.
  • ·Standard and interoperable: RFC 7519 is widely implemented across every major language and platform. JWT libraries exist for Node.js, Python, Java, Go, Ruby, PHP, .NET, and more.
  • ·Algorithm flexibility: Supports both symmetric (HMAC) and asymmetric (RSA, ECDSA) signing, so you can choose the trust model that fits your architecture.

Limitations and Tradeoffs

JWTs cannot be easily revoked before they expire. Understand this tradeoff before choosing them over opaque session tokens.
  • ·Revocation is hard: Because JWTs are stateless, there is no central registry to mark a token as invalidated. Three practical strategies exist: (1) maintain a server-side blocklist of revoked jti values, effective but erodes the stateless benefit; (2) use very short expiry times (5–15 minutes) paired with refresh tokens, the most common production approach; (3) token binding, ties the JWT to a specific TLS session or device, preventing replay from a different context.
  • ·Payload is public: The payload is only encoded, not encrypted. Don't put secrets or sensitive personal data in JWT claims unless you use JWE (JSON Web Encryption).
  • ·Key management overhead: Asymmetric JWTs require a public key infrastructure. Key rotation, JWKS endpoints, and key distribution add operational complexity.
  • ·Token size: JWTs are larger than opaque session tokens. A typical JWT with several claims is 200–500 bytes; complex tokens with many claims can exceed 1KB. This matters for high-QPS APIs where JWT overhead accumulates.
  • ·Signature must actually be verified: The security model only holds if every consuming service verifies the signature, checks expiry, validates the issuer, and enforces the audience. Skipping any of these checks creates real vulnerabilities.

Common Misconceptions

Misconception 1: JWTs are encrypted

A standard JWT (technically a JWS, JSON Web Signature) is signed, not encrypted. The payload is Base64url-encoded, which is trivially reversible. Anyone with the token string can read the payload contents without any key. If you need encrypted tokens, you need JWE (JSON Web Encryption, RFC 7516), which is a different format.

Misconception 2: Decoding a JWT proves it's valid

Decoding a JWT reveals its claims but proves nothing about authenticity. A token can be decoded successfully even if it's expired, issued by a fraudulent party, or had its payload modified. Validity requires cryptographic signature verification plus explicit claim validation. See the JWT Decoder vs Validator guide for a detailed breakdown.

Misconception 3: JWT = authentication

JWTs are a token format, not an authentication protocol. They are commonly used within authentication frameworks like OAuth 2.0 and OpenID Connect, but the authentication itself (password check, MFA, etc.) happens before the JWT is issued. The JWT is the proof of completed authentication, not the authentication mechanism itself.

Misconception 4: All JWTs are secure by default

A JWT is only as secure as its implementation. Common implementation failures include accepting the alg=none header value (disabling signature verification entirely), not validating the aud claim (allowing tokens meant for other services), and using weak HMAC secrets (allowing brute-force attacks against the signing key). RFC 7519 defines the format; security is the implementer's responsibility.

Ready to decode a token?
Use the free JWT decoder — paste any token for instant results, entirely in your browser.
Open JWT Decoder