Introduction
JSON Web Tokens (JWT) have become the standard for secure data transmission between parties. Whether you're building authentication systems, API integrations, or microservices architecture, understanding JWT is essential for modern web development.
In this guide, we'll dive deep into how JWTs work, explore their structure, discuss security considerations, and show you practical examples. Plus, learn how to debug JWTs using our free JWT Decoder tool in OptiLab.
What is a JWT?
A JSON Web Token is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure.
In simpler terms, JWTs are like digital passports that contain information about a user and are cryptographically signed to verify their authenticity.
JWT Structure
A JWT consists of three parts separated by dots (.):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1. Header
The header typically consists of two parts: the type of token (JWT) and the signing algorithm being used.
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload
The payload contains the claims. Claims are statements about an entity (typically, the user) and additional data.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
3. Signature
To create the signature, you take the encoded header, encoded payload, a secret, and sign it using the algorithm specified in the header.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Common JWT Claims
Standard claims that you'll frequently encounter:
- iss (Issuer): Identifies who issued the JWT
- sub (Subject): Identifies the subject of the JWT
- aud (Audience): Identifies recipients that should process the JWT
- exp (Expiration): Unix timestamp when the token expires
- nbf (Not Before): Unix timestamp before which token is invalid
- iat (Issued At): Unix timestamp when the token was issued
- jti (JWT ID): Unique identifier for the token
JWT Flow: Authentication Example
Here's how JWT authentication typically works in a web application:
- User Login: User submits credentials to the server
- Token Creation: Server verifies credentials and creates a JWT
- Token Response: Server sends JWT back to the client
- Token Storage: Client stores JWT (localStorage, cookie, etc.)
- Token Sending: Client includes JWT in subsequent requests
- Token Verification: Server verifies JWT signature and processes request
When to Use JWT
JWTs are ideal for:
- Authentication: Single Sign-On (SSO) implementations
- Authorization: Passing user permissions between services
- Information Exchange: Securely transmitting data between parties
- API Security: Securing RESTful APIs and microservices
- Stateless Sessions: When you don't want server-side session storage
JWT vs Session-Based Authentication
| JWT | Sessions |
|---|---|
| Stateless - no server storage needed | Stateful - requires session storage |
| Works well for microservices | Better for monolithic apps |
| Cross-domain friendly | Same-domain only |
| Cannot be easily revoked | Can be revoked immediately |
| Larger payload size | Smaller (just session ID) |
Security Best Practices
1. Always Use HTTPS
JWTs sent over HTTP can be intercepted. Always use HTTPS in production.
2. Set Expiration Times
Never create tokens that never expire. Short-lived tokens are more secure.
{
"exp": Math.floor(Date.now() / 1000) + (60 * 15)
}
3. Use Strong Secret Keys
Your secret key should be long, random, and stored securely. Use environment variables.
4. Validate All Claims
Don't just validate the signature. Check issuer, audience, and expiration.
5. Don't Store Sensitive Data
JWT payloads are base64 encoded, not encrypted. Anyone can decode and read them.
6. Implement Refresh Tokens
Use short-lived access tokens with longer-lived refresh tokens for better security.
Debugging JWTs with OptiLab
When working with JWTs, you often need to decode and inspect them. Our JWT Decoder tool in OptiLab makes this easy:
- Decode: View header, payload, and signature sections
- Validate: Verify token structure and format
- Inspect: Read all claims in human-readable format
- Debug: Quickly identify token issues during development
Implementing JWT in Node.js
Here's a practical example using the jsonwebtoken package:
Installation
npm install jsonwebtoken
Creating a Token
const jwt = require('jsonwebtoken');
function generateToken(user) {
return jwt.sign(
{
userId: user.id,
email: user.email,
role: user.role
},
process.env.JWT_SECRET,
{
expiresIn: '15m',
issuer: 'https://cekapcoder.com',
audience: 'cekapcoder-api'
}
);
}
Verifying a Token
function verifyToken(token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
issuer: 'https://cekapcoder.com',
audience: 'cekapcoder-api'
});
return { valid: true, decoded };
} catch (error) {
return {
valid: false,
error: error.message
};
}
}
Common JWT Algorithms
HS256 (HMAC with SHA-256)
Uses a shared secret. Simple and fast, but secret must be kept secure on both sides.
RS256 (RSA Signature with SHA-256)
Uses public/private key pair. More secure for distributed systems. Private key signs, public key verifies.
ES256 (ECDSA using P-256 and SHA-256)
Similar to RS256 but uses elliptic curve cryptography. Smaller signatures, better performance.
JWT Troubleshooting
"Invalid Token" Errors
- Check if the token is expired
- Verify the signature matches your secret/key
- Ensure the algorithm matches what was used to sign
- Use JWT Decoder to inspect the token
Token Too Large
- Reduce payload size by removing unnecessary claims
- Use reference tokens instead of self-contained tokens
- Consider storing user data in your database and just include an ID
Conclusion
JWTs are a powerful tool for modern web applications. They're stateless, scalable, and work great for distributed systems. However, they require careful attention to security practices.
Key takeaways:
- Always use HTTPS and strong secret keys
- Set appropriate expiration times
- Never store sensitive data in JWT payloads
- Use refresh tokens for better user experience
- Validate all claims, not just the signature
Ready to work with JWTs? Try our JWT Decoder tool in OptiLab to inspect and debug your tokens.