Skill

Validate JWT Tokens Securely

Expert knowledge resource for validating JSON Web Tokens (JWT) with secure signature verification, algorithm confusion prevention, and comprehensive claim

Works with githubjwt

91
Spark score
out of 100
Updated 5 months ago
Version 1.0.0
Models

Add to Favorites

Why it matters

Ensure the integrity and authenticity of your applications by rigorously validating JSON Web Tokens (JWTs). This asset provides expert-level checks against common vulnerabilities, ensuring only legitimate tokens grant access.

Outcomes

What it gets done

01

Verify JWT signature using appropriate algorithms and keys.

02

Validate token expiration, issuer, and audience claims.

03

Prevent algorithm confusion and other common JWT attacks.

04

Inspect token structure and identify potential security issues.

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/vb-jwt-token-validator | bash

Overview

JWT Token Validator

Expert knowledge resource covering JWT validation principles, security best practices, and implementation patterns with concrete code examples in JavaScript, Python, and Go. Use when implementing or auditing JWT validation logic, preventing algorithm confusion attacks, or setting up secure token verification with JWKS endpoints.

What it does

This skill provides expert knowledge on JSON Web Token (JWT) validation, security analysis, and implementation. It covers JWT structure (header, payload, signature), critical validation steps including signature verification, algorithm validation, expiration checks, issuer verification, audience validation, and not-before checks. The source material includes detailed code examples demonstrating secure validation patterns and common vulnerability mitigations like algorithm confusion attack prevention.

When to use - and when NOT to

Use this skill when implementing authentication systems that rely on JWTs, auditing existing JWT validation code for security vulnerabilities, debugging token expiration or claim validation issues, or setting up JWT validation with JWKS endpoints. It's useful when you need to validate tokens with specific algorithm requirements or when implementing custom claim validation logic.

When NOT to use: Don't use this for generating or signing JWTs (the source material focuses on validation only), and avoid it if you're working with non-JWT token formats like SAML or OAuth opaque tokens.

Inputs and outputs

Inputs: JWT token strings, secret keys or public keys for verification, expected issuer and audience values, JWKS endpoint URLs, algorithm specifications, and custom claim validation requirements.

Outputs: Validation results indicating token validity, decoded payload data when valid, specific error messages for validation failures (expired, invalid signature, algorithm mismatch), security analysis reports identifying vulnerabilities, and validation code examples in JavaScript, Python, or Go.

Integrations

The source material includes implementation examples using:

  • jsonwebtoken (Node.js): JavaScript library for JWT verification with explicit algorithm specification and claim validation
  • PyJWT (Python): Python library with comprehensive validation options and JWKS support
  • jwt-go (Go): Go implementation with RSA signature method validation
  • cryptography (Python): For handling key serialization and conversions
  • requests (Python): For fetching public keys from JWKS endpoints

Here's a secure JavaScript validation example from the source:

const jwt = require('jsonwebtoken');

function validateToken(token, secret) {
  try {
    const decoded = jwt.verify(token, secret, {
      algorithms: ['HS256'], // Explicitly allow only specific algorithms
      issuer: 'your-app.com',
      audience: 'api.your-app.com',
      clockTolerance: 30 // 30 seconds clock skew tolerance
    });
    return { valid: true, payload: decoded };
  } catch (error) {
    return { valid: false, error: error.message };
  }
}

Who it's for

Backend developers implementing authentication and authorization systems, security engineers auditing JWT implementations for vulnerabilities, DevOps engineers configuring production token validation, and API developers integrating with OAuth 2.0 or OpenID Connect providers. This skill is useful for developers who need to understand the security implications of different JWT validation approaches beyond basic library usage.

Source README

JWT Token Validator Expert

You are an expert in JSON Web Token (JWT) validation, security analysis, and implementation. You possess deep knowledge of JWT structure, cryptographic algorithms, security vulnerabilities, and best practices for token validation across different programming languages and frameworks.

JWT Structure and Validation Principles

Core Components

  • Header: Contains algorithm and token type information
  • Payload: Contains claims (registered, public, and private)
  • Signature: Cryptographic signature ensuring token integrity

Critical Validation Steps

  1. Signature Verification: Always verify using the correct algorithm and secret/public key
  2. Algorithm Validation: Prevent algorithm confusion attacks (e.g., RS256 vs HS256)
  3. Expiration Check: Validate exp claim against current time with clock skew tolerance
  4. Issuer Verification: Validate iss claim matches expected issuer
  5. Audience Validation: Ensure aud claim contains expected audience
  6. Not Before Check: Validate nbf claim if present

Security Best Practices

Algorithm Security

// SECURE: Explicitly specify allowed algorithms
const jwt = require('jsonwebtoken');

function validateToken(token, secret) {
  try {
    const decoded = jwt.verify(token, secret, {
      algorithms: ['HS256'], // Explicitly allow only specific algorithms
      issuer: 'your-app.com',
      audience: 'api.your-app.com',
      clockTolerance: 30 // 30 seconds clock skew tolerance
    });
    return { valid: true, payload: decoded };
  } catch (error) {
    return { valid: false, error: error.message };
  }
}

// INSECURE: Don't do this - vulnerable to algorithm confusion
// jwt.verify(token, secret); // No algorithm specification

Python Implementation with Comprehensive Validation

import jwt
from datetime import datetime, timezone
import requests
from cryptography.hazmat.primitives import serialization

class JWTValidator:
    def __init__(self, issuer, audience, jwks_url=None):
        self.issuer = issuer
        self.audience = audience
        self.jwks_url = jwks_url
        self.public_keys = {}
    
    def get_public_key(self, kid):
        """Fetch public key from JWKS endpoint"""
        if kid in self.public_keys:
            return self.public_keys[kid]
        
        if self.jwks_url:
            response = requests.get(self.jwks_url)
            jwks = response.json()
            
            for key in jwks['keys']:
                if key['kid'] == kid:
                    # Convert JWK to PEM format
                    public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
                    self.public_keys[kid] = public_key
                    return public_key
        
        raise ValueError(f"Public key not found for kid: {kid}")
    
    def validate_token(self, token):
        try:
            # Decode header to get algorithm and key ID
            header = jwt.get_unverified_header(token)
            
            # Security check: Ensure algorithm is acceptable
            allowed_algorithms = ['RS256', 'RS384', 'RS512']
            if header.get('alg') not in allowed_algorithms:
                return {'valid': False, 'error': 'Invalid algorithm'}
            
            # Get public key for verification
            public_key = self.get_public_key(header.get('kid'))
            
            # Comprehensive token validation
            payload = jwt.decode(
                token,
                public_key,
                algorithms=[header.get('alg')],
                issuer=self.issuer,
                audience=self.audience,
                options={
                    'verify_signature': True,
                    'verify_exp': True,
                    'verify_nbf': True,
                    'verify_iat': True,
                    'verify_aud': True,
                    'verify_iss': True,
                    'require_exp': True,
                    'require_iat': True
                }
            )
            
            # Additional custom validations
            if not self.validate_custom_claims(payload):
                return {'valid': False, 'error': 'Custom claim validation failed'}
            
            return {'valid': True, 'payload': payload}
            
        except jwt.ExpiredSignatureError:
            return {'valid': False, 'error': 'Token has expired'}
        except jwt.InvalidTokenError as e:
            return {'valid': False, 'error': str(e)}
    
    def validate_custom_claims(self, payload):
        """Implement custom business logic validation"""
        # Example: Check if user is active
        if payload.get('status') == 'inactive':
            return False
        
        # Example: Validate scope claims
        required_scopes = {'read', 'write'}
        token_scopes = set(payload.get('scope', '').split())
        if not required_scopes.issubset(token_scopes):
            return False
        
        return True

Common Vulnerabilities and Mitigations

Algorithm Confusion Attack Prevention

// Go implementation with secure algorithm validation
package main

import (
    "errors"
    "github.com/dgrijalva/jwt-go"
)

func ValidateJWT(tokenString string, publicKey interface{}) (*jwt.Token, error) {
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        // Critical: Validate the algorithm
        if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
            return nil, errors.New("unexpected signing method")
        }
        
        // Ensure it's specifically RS256
        if token.Method.Alg() != "RS256" {
            return nil, errors.New("invalid algorithm")
        }
        
        return publicKey, nil
    })
    
    if err != nil {
        return nil, err
    }
    
    // Validate standard claims
    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        if !claims.VerifyIssuer("expected-issuer", true) {
            return nil, errors.New("invalid issuer")
        }
        if !claims.VerifyAudience("expected-audience", true) {
            return nil, errors.New("invalid audience")
        }
    }
    
    return token, nil
}

Token Inspection and Debugging

Safe Token Decoding (Without Verification)

function inspectToken(token) {
  try {
    // Decode without verification for inspection
    const decoded = jwt.decode(token, { complete: true });
    
    const analysis = {
      header: decoded.header,
      payload: decoded.payload,
      issues: [],
      recommendations: []
    };
    
    // Security analysis
    if (decoded.header.alg === 'none') {
      analysis.issues.push('CRITICAL: Algorithm "none" is not secure');
    }
    
    if (decoded.header.alg === 'HS256' && !decoded.header.typ) {
      analysis.recommendations.push('Consider adding "typ": "JWT" to header');
    }
    
    // Expiration analysis
    if (decoded.payload.exp) {
      const expDate = new Date(decoded.payload.exp * 1000);
      const now = new Date();
      
      if (expDate < now) {
        analysis.issues.push(`Token expired on ${expDate.toISOString()}`);
      } else {
        const timeToExpiry = expDate - now;
        analysis.recommendations.push(`Token expires in ${Math.round(timeToExpiry / 1000 / 60)} minutes`);
      }
    } else {
      analysis.issues.push('No expiration claim found');
    }
    
    return analysis;
  } catch (error) {
    return { error: 'Invalid token format', details: error.message };
  }
}

Production Configuration Examples

Environment-Specific Validation Settings

# JWT validation configuration
jwt:
  validation:
    algorithms:
      - RS256
      - RS384
    issuer: "https://auth.company.com"
    audience: 
      - "api.company.com"
      - "mobile.company.com"
    clock_skew_seconds: 30
    require_exp: true
    require_iat: true
    require_nbf: false
    
  jwks:
    url: "https://auth.company.com/.well-known/jwks.json"
    cache_ttl_seconds: 300
    timeout_seconds: 5
    
  custom_validation:
    require_scope: true
    allowed_token_types: ["access_token"]
    max_token_age_hours: 24

Key Recommendations

  1. Never trust algorithm from token header blindly - always validate against allowed algorithms
  2. Implement proper key rotation - support multiple valid keys during rotation periods
  3. Use short expiration times - typically 15 minutes for access tokens
  4. Validate all relevant claims - don't skip issuer, audience, or expiration checks
  5. Implement rate limiting - prevent token validation abuse
  6. Log validation failures - monitor for potential attacks
  7. Use established libraries - avoid implementing JWT validation from scratch
  8. Cache public keys securely - but implement proper cache invalidation

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.