Back to Blog
Security10 min read

JWT Authentication: A Developer's Guide

Implement secure authentication with JSON Web Tokens. Learn about JWT structure, security considerations, and best practices.

What is JWT?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. JWTs are commonly used for authentication and information exchange in web applications.

Key Benefits of JWT

  • Stateless: No need to store session data on the server
  • Compact: Lightweight and efficient for transmission
  • Self-contained: Contains all necessary information
  • Secure: Digitally signed to prevent tampering
  • Cross-domain: Works across different domains and services

JWT Structure

A JWT consists of three parts separated by dots (.): Header, Payload, and Signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header

Specifies the algorithm and token type

1{
2  "alg": "HS256",
3  "typ": "JWT"
4}

Payload

Contains claims (statements about an entity)

1{
2  "sub": "1234567890",
3  "name": "John Doe",
4  "iat": 1516239022,
5  "exp": 1516242622,
6  "role": "admin"
7}

Signature

Verifies the token hasn't been tampered with

1HMACSHA256(
2  base64UrlEncode(header) + "." +
3  base64UrlEncode(payload),
4  secret
5)

How JWT Authentication Works

The JWT authentication flow involves several steps between the client, server, and protected resources.

1

User Login

Client sends credentials to authentication server

2

Token Generation

Server validates credentials and creates JWT

3

Token Return

Server sends JWT back to client

4

Subsequent Requests

Client includes JWT in Authorization header

5

Token Verification

Server validates JWT and processes request

Implementation Examples

Node.js with Express (Server-side)

1const jwt = require('jsonwebtoken');
2const bcrypt = require('bcrypt');
3
4// Login endpoint
5app.post('/login', async (req, res) => {
6  const { email, password } = req.body;
7  
8  try {
9    // Find user in database
10    const user = await User.findOne({ email });
11    if (!user) {
12      return res.status(401).json({ error: 'Invalid credentials' });
13    }
14    
15    // Verify password
16    const isValidPassword = await bcrypt.compare(password, user.passwordHash);
17    if (!isValidPassword) {
18      return res.status(401).json({ error: 'Invalid credentials' });
19    }
20    
21    // Create JWT
22    const token = jwt.sign(
23      { 
24        userId: user.id, 
25        email: user.email,
26        role: user.role 
27      },
28      process.env.JWT_SECRET,
29      { expiresIn: '1h' }
30    );
31    
32    res.json({ token, user: { id: user.id, email: user.email } });
33  } catch (error) {
34    res.status(500).json({ error: 'Server error' });
35  }
36});

Frontend JavaScript (Client-side)

1class AuthService {
2  constructor() {
3    this.token = localStorage.getItem('token');
4  }
5  
6  async login(email, password) {
7    try {
8      const response = await fetch('/api/login', {
9        method: 'POST',
10        headers: {
11          'Content-Type': 'application/json'
12        },
13        body: JSON.stringify({ email, password })
14      });
15      
16      if (!response.ok) {
17        throw new Error('Login failed');
18      }
19      
20      const data = await response.json();
21      this.token = data.token;
22      localStorage.setItem('token', this.token);
23      
24      return data;
25    } catch (error) {
26      console.error('Login error:', error);
27      throw error;
28    }
29  }
30}

Security Considerations

Token Storage

  • Avoid localStorage for sensitive tokens (XSS vulnerable)
  • Use httpOnly cookies for automatic inclusion
  • Consider secure, sameSite cookie attributes
  • Implement proper CSRF protection with cookies

Secret Management

  • Use strong, randomly generated secrets
  • Store secrets securely (environment variables, key vaults)
  • Rotate secrets regularly
  • Consider asymmetric algorithms (RS256) for microservices

Best Practices

Use HTTPS Always

Never transmit JWTs over unencrypted connections

Validate All Claims

Check expiration, issuer, audience, and other relevant claims

Minimize Payload Size

Include only necessary information in the JWT payload

Implement Token Refresh

Use short-lived access tokens with refresh token mechanism

Handle Token Expiration Gracefully

Implement automatic token renewal and logout on expiration

JWT vs Alternatives

Session-based Authentication

Pros: Server-side control, easy revocation, smaller client storage

Cons: Requires server-side storage, doesn't scale horizontally as easily

OAuth 2.0 / OpenID Connect

Pros: Industry standard, delegation, comprehensive flows

Cons: More complex implementation, requires additional infrastructure

API Keys

Pros: Simple implementation, good for service-to-service auth

Cons: No expiration, limited scope control, security concerns

Common JWT Claims

ClaimDescriptionExample
issIssuer"https://auth.example.com"
subSubject (user ID)"user123"
audAudience"api.example.com"
expExpiration time1516242622
iatIssued at1516239022
jtiJWT ID"abc123"

Conclusion

JWT provides a robust solution for stateless authentication in modern web applications. While powerful, it requires careful implementation with attention to security best practices. Consider your specific use case, security requirements, and infrastructure constraints when choosing JWT over alternative authentication methods.

Test JWT Tokens

Debug and validate your JWT tokens with our interactive decoder and validator tool.

Open JWT Decoder