JSON Web Tokens (JWTs) are everywhere in modern web authentication. Nearly every new application, API, and cloud service uses JWTs in some form. Understanding how they work — and more importantly, how they can go wrong — is essential for any developer building secure applications. This guide covers everything from the basics to security pitfalls.
> Debug a token: Use our free [JWT Decoder](/tools/jwt-decoder) to instantly decode any JWT and inspect its header, payload, and claims — no signup required.
What is a JWT?
A JWT (pronounced "jot") is a compact, URL-safe token for representing claims between two parties. In practice, JWTs are most commonly used for authentication and API authorisation. When a user logs into an application, the server issues a JWT that the client stores and sends with subsequent requests to prove identity.
A JWT looks like three Base64URL-encoded strings separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInJvbGUiOiJhZG1pbiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
This is not encrypted — it is encoded. Anyone who has the token can decode and read its contents using our [Base64 decoder](/tools/base64). The security comes from the cryptographic signature, not from hiding the data.
The Three Parts of a JWT
Advertisement
Part 1: Header
The header contains the token type and the signing algorithm:
{
"alg": "HS256",
"typ": "JWT"
}Part 2: Payload (Claims)
The payload contains the "claims" — statements about the user and additional metadata:
{
"sub": "user_12345",
"name": "Alice Johnson",
"role": "admin",
"iat": 1703155200,
"exp": 1703241600
}Standard claim names:
sub— subject (the user identifier)iss— issuer (who issued the token)aud— audience (who the token is intended for)iat— issued at (Unix timestamp of token creation)exp— expiration (Unix timestamp when the token expires)
Part 3: Signature
The signature verifies that the token has not been tampered with. For HMAC-SHA256 (HS256):
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
Without knowing the secret key, it is computationally infeasible to create a valid signature.
How JWT Authentication Works
1. User submits login credentials (username and password)
2. Server validates credentials against the database
3. Server creates a JWT with the user's ID, roles, and expiration time, signed with a secret key
4. Server returns the JWT to the client
5. Client stores the JWT (typically in memory or a cookie)
6. Client includes the JWT in the Authorization header: Authorization: Bearer [token]
7. Server receives the request, validates the JWT signature, checks expiration, and extracts the user's identity from the payload — without querying the database
This is the key advantage of JWTs: the server can verify identity entirely from the token itself, without a database lookup. This makes JWTs ideal for distributed systems and microservices.
Signing Algorithms
HS256 (HMAC-SHA256): A symmetric algorithm — the same secret key is used to sign and verify. Simple and fast, but the signing secret must be kept confidential on the server.
RS256 (RSA-SHA256): An asymmetric algorithm. A private key signs the token; a public key verifies it. Services can verify tokens without knowing the private signing key. Best for multi-service architectures.
ES256 (ECDSA): Like RS256 but uses elliptic curve cryptography. Produces shorter signatures and is computationally faster while maintaining equivalent security.
For more on hashing algorithms, see our [MD5 vs SHA-256 comparison](/blog/md5-sha256-difference).
Critical Security Vulnerabilities
JWTs have a history of critical security vulnerabilities, mostly from implementation mistakes:
The "alg:none" attack: Early JWT libraries accepted tokens with "alg": "none" and no signature, treating them as valid. Always explicitly specify allowed algorithms in your JWT library configuration and reject none.
HS256/RS256 confusion: If a library accepts both symmetric and asymmetric algorithms and a server uses an RS256 public key as the HS256 secret, an attacker can sign their own tokens with the known public key.
Weak secrets: HS256 tokens signed with short or common secrets can be brute-forced. Use a cryptographically random secret of at least 256 bits (32 bytes). Generate a strong secret with our [Password Generator](/tools/password-generator).
Missing expiration: Tokens without exp claims are valid forever. Always set short expiration times (15 minutes for access tokens).
Storing JWTs in localStorage: localStorage is accessible to JavaScript, making it vulnerable to XSS attacks. Store access tokens in memory; store refresh tokens in httpOnly cookies.
Access Tokens vs. Refresh Tokens
Short-lived access tokens (5–15 minutes) authorise API requests. When they expire, the client uses a long-lived refresh token to get a new access token without re-authentication.
Refresh tokens should be:
- Stored in
httpOnlycookies - Rotated on every use
- Invalidated on logout
Decoding JWTs for Debugging
Because JWT payloads are just Base64URL-encoded JSON, you can decode them to inspect their contents — useful for debugging and understanding what claims are present. Decoding does not validate the signature.
[Use ToolHub's JWT Decoder](/tools/jwt-decoder) to paste a token and instantly see the decoded header and payload without sending anything to a server.
When to Use JWTs
Good use cases:
- API authentication
- Single sign-on (SSO) across services
- Stateless microservices
- Mobile app authentication
Better alternatives exist for:
- Simple single-server session management (traditional server-side sessions are easier and more revocable)
- Storing sensitive data in tokens (remember: not encrypted)
- Use cases where immediate token revocation is critical
Frequently Asked Questions
Q: Is a JWT the same as an API key?
No. An API key is a simple static secret shared between client and server. A JWT is a self-contained, cryptographically signed token that includes claims about the user's identity and can be verified without a database lookup.
Q: Can I decode a JWT without the secret key?
Yes — the header and payload are just Base64URL-encoded and can be decoded by anyone. However, you cannot verify the signature or create a valid JWT without the secret/private key. Use our [JWT Decoder](/tools/jwt-decoder) to inspect any token's payload.
Q: Why does my JWT expire so quickly?
Short expiry times are a security best practice. If an access token is stolen, a short expiry limits the damage window. The solution is refresh tokens — which allow seamless renewal without forcing users to log in again.
Q: Is JWT better than session-based authentication?
Neither is universally better. JWTs excel in stateless, distributed systems. Session-based auth is simpler to implement and easier to revoke for single-server applications. The right choice depends on your architecture.
Conclusion
JWTs are a powerful but nuanced authentication mechanism. Understanding the three-part structure, how signatures work, the difference between signing algorithms, and the critical security pitfalls is essential for implementing them safely. [Use ToolHub's JWT Decoder](/tools/jwt-decoder) whenever you need to inspect a token during development or debugging.