JWT Authentication

Secure JSON Web Token authentication for webMCP applications. Implement stateless authentication with scope-based authorization.

JWT Authentication Features

Comprehensive JWT implementation with advanced security features

Secure Token Signing

Sign JWT tokens with cryptographically secure algorithms

  • HMAC-SHA256 (HS256) signing
  • RSA-SHA256 (RS256) support
  • ECDSA (ES256) for enhanced security
  • Custom signing key rotation

Flexible Expiration

Configure token expiration and refresh strategies

  • Configurable expiration times
  • Automatic token refresh
  • Sliding session windows
  • Remember me functionality

Scope-Based Permissions

Fine-grained access control with JWT scopes

  • Custom scope definitions
  • Role-based access control
  • Resource-level permissions
  • Dynamic scope validation

JWT Token Structure

Understanding the structure of webMCP JWT tokens

Header

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

Specifies the signing algorithm and token type

Payload

{
  "sub": "user123",
  "name": "John Doe",
  "iat": 1640995200,
  "exp": 1640998800,
  "scopes": [
    "webmcp:read",
    "webmcp:write",
    "user:profile"
  ]
}

Contains user data, claims, and permissions

Signature

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

Cryptographic signature for verification

Implementation Examples

Practical examples for implementing JWT authentication

Basic JWT Authentication

Simple JWT token generation and validation

JavaScript
import { WebMCPProcessor } from '@webmcp/core';

const processor = new WebMCPProcessor({
  security: {
    jwt: {
      secret: process.env.JWT_SECRET,
      expiresIn: '1h',
      algorithm: 'HS256'
    }
  }
});

// Generate JWT token
const user = { id: 123, email: 'user@example.com' };
const token = processor.generateJWTToken(user, {
  scopes: ['webmcp:read', 'webmcp:write'],
  expiresIn: '24h'
});

// Validate JWT token
const validateToken = (token) => {
  try {
    const decoded = processor.verifyJWTToken(token);
    console.log('Valid token:', decoded.payload);
    return decoded;
  } catch (error) {
    console.error('Invalid token:', error.message);
    return null;
  }
};

// Use in middleware
app.use('/api', (req, res, next) => {
  const token = req.headers.authorization?.replace('Bearer ', '');
  const decoded = validateToken(token);
  
  if (!decoded) {
    return res.status(401).json({ error: 'Invalid token' });
  }
  
  req.user = decoded.payload;
  next();
});

Advanced JWT Configuration

Production-ready JWT setup with refresh tokens

JavaScript
const jwtConfig = {
  // Access token configuration
  accessToken: {
    secret: process.env.JWT_ACCESS_SECRET,
    expiresIn: '15m', // Short-lived access tokens
    algorithm: 'HS256',
    issuer: 'webmcp-api',
    audience: 'webmcp-client'
  },
  
  // Refresh token configuration
  refreshToken: {
    secret: process.env.JWT_REFRESH_SECRET,
    expiresIn: '7d', // Long-lived refresh tokens
    algorithm: 'HS256'
  },
  
  // Security options
  security: {
    clockTolerance: 30, // 30 seconds clock skew tolerance
    maxAge: '1h', // Maximum token age regardless of exp
    jti: true, // Include JWT ID for revocation
    notBefore: true // Include nbf claim
  }
};

const processor = new WebMCPProcessor({ security: { jwt: jwtConfig } });

// Generate token pair
const generateTokenPair = (user) => {
  const accessToken = processor.generateJWTToken(user, {
    type: 'access',
    scopes: user.permissions,
    expiresIn: jwtConfig.accessToken.expiresIn
  });
  
  const refreshToken = processor.generateJWTToken(user, {
    type: 'refresh',
    expiresIn: jwtConfig.refreshToken.expiresIn
  });
  
  return { accessToken, refreshToken };
};

// Refresh access token
const refreshAccessToken = (refreshToken) => {
  try {
    const decoded = processor.verifyJWTToken(refreshToken);
    
    if (decoded.payload.type !== 'refresh') {
      throw new Error('Invalid refresh token');
    }
    
    const user = { 
      id: decoded.payload.sub, 
      permissions: decoded.payload.scopes 
    };
    
    return processor.generateJWTToken(user, {
      type: 'access',
      scopes: user.permissions,
      expiresIn: jwtConfig.accessToken.expiresIn
    });
  } catch (error) {
    throw new Error('Refresh token expired or invalid');
  }
};

Scope-Based Authorization

Implement fine-grained permissions with JWT scopes

JavaScript
// Define scope hierarchy
const scopeHierarchy = {
  'admin': ['user:*', 'webmcp:*', 'system:*'],
  'user:write': ['user:read'],
  'webmcp:write': ['webmcp:read'],
  'webmcp:optimize': ['webmcp:read']
};

// Scope validation middleware
const requireScopes = (requiredScopes) => {
  return (req, res, next) => {
    const userScopes = req.user?.scopes || [];
    
    const hasRequiredScopes = requiredScopes.every(required => 
      userScopes.some(userScope => {
        // Direct match
        if (userScope === required) return true;
        
        // Wildcard match
        if (userScope.endsWith('*')) {
          const base = userScope.slice(0, -1);
          return required.startsWith(base);
        }
        
        // Hierarchy match
        if (scopeHierarchy[userScope]) {
          return scopeHierarchy[userScope].some(inherited => 
            inherited === required || 
            (inherited.endsWith('*') && required.startsWith(inherited.slice(0, -1)))
          );
        }
        
        return false;
      })
    );
    
    if (!hasRequiredScopes) {
      return res.status(403).json({
        error: 'Insufficient permissions',
        required: requiredScopes,
        provided: userScopes
      });
    }
    
    next();
  };
};

// Usage in routes
app.get('/api/user/profile', 
  requireScopes(['user:read']), 
  (req, res) => {
    res.json({ profile: getUserProfile(req.user.sub) });
  }
);

app.post('/api/webmcp/optimize', 
  requireScopes(['webmcp:optimize']), 
  (req, res) => {
    // Process optimization request
    const result = processor.optimize(req.body);
    res.json(result);
  }
);

app.delete('/api/admin/users/:id', 
  requireScopes(['admin']), 
  (req, res) => {
    // Admin-only operation
    deleteUser(req.params.id);
    res.json({ success: true });
  }
);

Python JWT Implementation

JWT authentication in Python applications

Python
from webmcp_core import WebMCPProcessor, JWTConfig
from datetime import datetime, timedelta
import jwt
import os

# Configure JWT
jwt_config = JWTConfig(
    secret=os.getenv('JWT_SECRET'),
    algorithm='HS256',
    expires_in=3600,  # 1 hour
    issuer='webmcp-api',
    audience='webmcp-client'
)

processor = WebMCPProcessor(security={'jwt': jwt_config})

class JWTAuth:
    def __init__(self, processor):
        self.processor = processor
        
    def generate_token(self, user_id, scopes=None, expires_in=None):
        payload = {
            'sub': str(user_id),
            'iat': datetime.utcnow(),
            'exp': datetime.utcnow() + timedelta(seconds=expires_in or 3600),
            'iss': 'webmcp-api',
            'aud': 'webmcp-client'
        }
        
        if scopes:
            payload['scopes'] = scopes
            
        return self.processor.generate_jwt_token(payload)
    
    def verify_token(self, token):
        try:
            return self.processor.verify_jwt_token(token)
        except jwt.ExpiredSignatureError:
            raise ValueError('Token has expired')
        except jwt.InvalidTokenError:
            raise ValueError('Invalid token')
    
    def require_scopes(self, required_scopes):
        def decorator(func):
            def wrapper(*args, **kwargs):
                # Extract token from request context
                token = get_current_token()  # Implementation specific
                
                try:
                    decoded = self.verify_token(token)
                    user_scopes = decoded.get('scopes', [])
                    
                    if not all(scope in user_scopes for scope in required_scopes):
                        raise PermissionError('Insufficient scopes')
                        
                    return func(*args, **kwargs)
                except (ValueError, PermissionError) as e:
                    raise HTTPException(status_code=403, detail=str(e))
            return wrapper
        return decorator

# Usage example
auth = JWTAuth(processor)

@app.route('/api/login', methods=['POST'])
def login():
    # Authenticate user
    user = authenticate_user(request.json['email'], request.json['password'])
    
    if user:
        token = auth.generate_token(
            user.id, 
            scopes=['user:read', 'webmcp:read'],
            expires_in=86400  # 24 hours
        )
        return {'token': token, 'user': user.to_dict()}
    
    return {'error': 'Invalid credentials'}, 401

@auth.require_scopes(['webmcp:write'])
@app.route('/api/webmcp/process', methods=['POST'])
def process_webmcp():
    result = processor.parse_webmcp(request.json['html'])
    return result.to_dict()

Security Best Practices

Essential security practices for JWT implementation

Token Security

Use Strong Secrets

Use cryptographically secure secrets for JWT signing

Minimum 256 bits of entropy, store in environment variables

Short Access Token Expiry

Keep access tokens short-lived to limit exposure

Use 15-30 minute expiry with refresh token rotation

Algorithm Verification

Always verify the JWT algorithm to prevent attacks

Explicitly specify allowed algorithms in verification

Token Storage

Secure Client Storage

Store tokens securely on the client side

Use httpOnly cookies or secure browser storage APIs

Token Transmission

Always transmit tokens over secure connections

Use HTTPS and proper Authorization headers

Token Revocation

Implement token revocation for compromised tokens

Maintain a blacklist or use short-lived tokens with refresh

Implementation Security

Validate All Claims

Validate all JWT claims including iss, aud, exp

Check issuer, audience, expiration, and not-before claims

Rate Limiting

Implement rate limiting for token endpoints

Limit login attempts and token refresh requests

Audit Logging

Log all authentication and authorization events

Log token generation, validation failures, and scope violations

Troubleshooting Guide

Common JWT issues and their solutions

Token Expired

Symptoms

  • 401 Unauthorized errors
  • Automatic logout
  • API requests failing

Solutions

  • Implement automatic token refresh
  • Check system clock synchronization
  • Adjust token expiration times
  • Implement sliding sessions

Invalid Signature

Symptoms

  • JWT verification failures
  • Signature mismatch errors

Solutions

  • Verify JWT secret configuration
  • Check algorithm consistency
  • Ensure proper key rotation
  • Validate token format

Insufficient Scopes

Symptoms

  • 403 Forbidden errors
  • Permission denied messages

Solutions

  • Review user role assignments
  • Check scope hierarchy configuration
  • Verify token includes required scopes
  • Update user permissions

Implement Secure Authentication

Start using JWT authentication to secure your webMCP applications with stateless authentication