or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-python-jwt

Module for generating and verifying JSON Web Tokens with multiple signature algorithms

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/python-jwt@4.1.x

To install, run

npx @tessl/cli install tessl/pypi-python-jwt@4.1.0

index.mddocs/

Python JWT

A Python library for generating and verifying JSON Web Tokens (JWTs) with support for multiple signature algorithms including RSA, ECDSA, HMAC, PSS, and EdDSA variants. Uses jwcrypto for cryptographic operations and provides comprehensive JWT validation capabilities.

Important Note: This package is deprecated and no longer maintained by the author. Using the library will trigger a deprecation warning at runtime.

Package Information

  • Package Name: python_jwt
  • Language: Python
  • Installation: pip install python_jwt
  • Dependencies: jwcrypto>=1.4.2
  • Python Version: 3.6+
  • License: MIT

Core Imports

import python_jwt as jwt
import jwcrypto.jwk as jwk
from datetime import datetime, timedelta

Basic Usage

import python_jwt as jwt
import jwcrypto.jwk as jwk
from datetime import timedelta

# Generate RSA key pair
key = jwk.JWK.generate(kty='RSA', size=2048)

# Create payload with custom claims
payload = {'user': 'john', 'role': 'admin', 'permissions': ['read', 'write']}

# Generate JWT token with 5 minute expiration
token = jwt.generate_jwt(payload, key, 'PS256', timedelta(minutes=5))

# Verify the token
header, claims = jwt.verify_jwt(token, key, ['PS256'])

# Access claims
user_id = claims['user']
role = claims['role']

Capabilities

Token Generation

Generate JSON Web Tokens with custom claims, automatic timestamps, and replay attack protection.

def generate_jwt(claims, priv_key=None, algorithm='PS512', lifetime=None, 
                 expires=None, not_before=None, jti_size=16, other_headers=None):
    """
    Generate a JSON Web Token with specified claims and signing parameters.
    
    Args:
        claims (dict): The claims to include in the token
        priv_key (jwcrypto.jwk.JWK, optional): Private key for signing (None creates unsigned token)
        algorithm (str): Signature algorithm (default: 'PS512')
        lifetime (datetime.timedelta, optional): Token validity duration
        expires (datetime.datetime, optional): Explicit expiration time
        not_before (datetime.datetime, optional): Token valid-from time
        jti_size (int): Size of unique token ID in bytes (default: 16, 0 to omit)
        other_headers (dict, optional): Additional headers to include
    
    Returns:
        str: Unicode string containing the JWT
        
    Raises:
        ValueError: If other_headers redefines 'typ' or 'alg'
    """

Supported Algorithms: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, ES256K, EdDSA, HS256, HS384, HS512, none

Automatic Claims Added:

  • exp (expiration time): Based on lifetime or expires parameter
  • iat (issued at): Current UTC time when token is generated
  • nbf (not before): Based on not_before parameter or current time
  • jti (JWT ID): Random unique identifier for replay attack prevention

Usage Examples

Basic token generation:

# Simple token with automatic expiration
payload = {'sub': '1234567890', 'name': 'John Doe'}
token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1))

Token with explicit times:

from datetime import datetime

# Token valid from tomorrow for 1 week
not_before = datetime.utcnow() + timedelta(days=1)
expires = not_before + timedelta(weeks=1)
token = jwt.generate_jwt(payload, key, 'PS384', 
                        not_before=not_before, expires=expires)

Unsigned token (for testing):

# Create unsigned token (algorithm forced to 'none')
token = jwt.generate_jwt(payload, None, 'PS256')

Custom headers:

# Add custom headers
custom_headers = {'kid': 'key-id-123', 'cty': 'application/json'}
token = jwt.generate_jwt(payload, key, 'ES256', timedelta(minutes=30),
                        other_headers=custom_headers)

Token Verification

Verify JWT signatures and validate time-based claims with comprehensive security checks.

def verify_jwt(jwt, pub_key=None, allowed_algs=None, iat_skew=timedelta(),
               checks_optional=False, ignore_not_implemented=False):
    """
    Verify a JSON Web Token's signature and validate claims.
    
    Args:
        jwt (str): The JWT to verify
        pub_key (jwcrypto.jwk.JWK, optional): Public key for verification
        allowed_algs (list, optional): List of allowed signature algorithms (None defaults to empty list)
        iat_skew (datetime.timedelta): Clock skew tolerance for 'iat' claim
        checks_optional (bool): Whether typ/iat/nbf/exp claims are optional
        ignore_not_implemented (bool): Whether to ignore unsupported header properties
    
    Returns:
        tuple: (header, claims) containing parsed header and claims dictionaries
        
    Raises:
        Exception: Various exceptions if verification fails, including:
            - Invalid JWT format
            - Algorithm header not present or not in allowed list
            - Unknown or unsupported header properties
            - No public key provided but 'none' algorithm not allowed
            - Invalid 'typ' header (must be 'JWT')
            - Missing required claims (iat, nbf, exp) when checks_optional=False
            - Token issued in future (iat validation)
            - Token not yet valid (nbf validation)
            - Token expired (exp validation)
            - Signature verification failures
    """

Validation Checks Performed:

  • Algorithm must be in allowed_algs
  • Signature verification (unless algorithm is 'none')
  • Header 'typ' must be 'JWT'
  • Claims 'iat' must be in the past (with skew tolerance)
  • Claims 'nbf' must be in the past (not before)
  • Claims 'exp' must be in the future (expiration)

Usage Examples

Basic verification:

# Verify with specific algorithm
header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

Multiple allowed algorithms:

# Allow multiple signature algorithms
header, claims = jwt.verify_jwt(token, pub_key, ['RS256', 'PS256', 'ES256'])

Clock skew tolerance:

# Allow 30 seconds clock skew for distributed systems
header, claims = jwt.verify_jwt(token, pub_key, ['PS256'], 
                               iat_skew=timedelta(seconds=30))

Relaxed validation:

# Make time-based claims optional
header, claims = jwt.verify_jwt(token, pub_key, ['HS256'], 
                               checks_optional=True)

Token Processing

Extract header and claims from JWT without signature verification for inspection purposes.

def process_jwt(jwt):
    """
    Process a JWT without verifying it to extract header and claims.
    
    Args:
        jwt (str): The JWT to process
    
    Returns:
        tuple: (header, claims) containing parsed header and claims dictionaries
        
    Raises:
        Exception: If JWT format is invalid (must match pattern: header.payload.signature)
    """

Use this before verify_jwt when you need to examine token contents to determine verification parameters (e.g., selecting the appropriate public key based on issuer).

Usage Examples

Pre-verification inspection:

# Examine token before verification
header, claims = jwt.process_jwt(token)

# Select appropriate key based on issuer
issuer = claims.get('iss')
if issuer == 'auth.example.com':
    pub_key = load_example_key()
elif issuer == 'auth.other.com':
    pub_key = load_other_key()

# Now verify with the correct key
verified_header, verified_claims = jwt.verify_jwt(token, pub_key, ['RS256'])

Algorithm inspection:

# Check algorithm before verification
header, claims = jwt.process_jwt(token)
algorithm = header.get('alg')

# Use algorithm-specific key
if algorithm.startswith('RS'):
    pub_key = rsa_public_key
elif algorithm.startswith('ES'):
    pub_key = ecdsa_public_key

verified_header, verified_claims = jwt.verify_jwt(token, pub_key, [algorithm])

Key Management

PEM Key Import/Export

Work with PEM-format keys for interoperability with other systems.

# Generate and export keys
key = jwk.JWK.generate(kty='RSA', size=2048)
priv_pem = key.export_to_pem(private_key=True, password=None)
pub_pem = key.export_to_pem()

# Import keys from PEM
priv_key = jwk.JWK.from_pem(priv_pem)
pub_key = jwk.JWK.from_pem(pub_pem)

# Use with JWT functions
token = jwt.generate_jwt(payload, priv_key, 'RS256', timedelta(hours=1))
header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

Key Types and Algorithms

Different key types support different signature algorithms:

# RSA keys (RS256, RS384, RS512, PS256, PS384, PS512)
rsa_key = jwk.JWK.generate(kty='RSA', size=2048)

# ECDSA keys (ES256, ES384, ES512, ES256K)
ec_key = jwk.JWK.generate(kty='EC', curve='P-256')  # For ES256
ec_key = jwk.JWK.generate(kty='EC', curve='P-384')  # For ES384
ec_key = jwk.JWK.generate(kty='EC', curve='P-521')  # For ES512

# EdDSA keys (EdDSA)
ed_key = jwk.JWK.generate(kty='OKP', curve='Ed25519')

# HMAC keys (HS256, HS384, HS512)
hmac_key = jwk.JWK.generate(kty='oct', size=256)

Security Features

Algorithm Verification

The library prevents algorithm confusion attacks by requiring explicit specification of allowed algorithms:

# Secure: explicitly allow only specific algorithms
header, claims = jwt.verify_jwt(token, pub_key, ['PS256'])

# Insecure: never pass None or empty list for allowed_algs
# This would allow any algorithm, including 'none'

Replay Attack Prevention

Generate unique token IDs (JTI) to detect and prevent replay attacks:

# Default: 16-byte (128-bit) random JTI
token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1))

# Custom JTI size
token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1), jti_size=32)

# Omit JTI (not recommended for security)
token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1), jti_size=0)

Time-based Validation

Comprehensive time-based claim validation with configurable clock skew:

# Strict time validation (default)
header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

# Allow clock skew for distributed systems
header, claims = jwt.verify_jwt(token, pub_key, ['RS256'], 
                               iat_skew=timedelta(minutes=1))

Exception Handling

The library may raise various exceptions during verification. Always wrap JWT operations in try-catch blocks:

try:
    header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])
    # Token is valid
    user_id = claims['sub']
except Exception as e:
    # Token verification failed
    print(f"JWT verification failed: {e}")
    # Handle invalid token (redirect to login, etc.)

Complete Example

import python_jwt as jwt
import jwcrypto.jwk as jwk
from datetime import datetime, timedelta

# Generate RSA key pair
key = jwk.JWK.generate(kty='RSA', size=2048)

# Create comprehensive payload
payload = {
    'sub': '1234567890',          # Subject (user ID)
    'name': 'John Doe',           # User name
    'iss': 'auth.example.com',    # Issuer
    'aud': 'api.example.com',     # Audience
    'roles': ['admin', 'user'],   # Custom claim
    'permissions': ['read', 'write', 'delete']
}

try:
    # Generate token with 1 hour expiration
    token = jwt.generate_jwt(
        payload, 
        key, 
        'PS256',  # RSA-PSS with SHA-256
        timedelta(hours=1),
        jti_size=16  # 128-bit unique token ID
    )
    
    print(f"Generated token: {token[:50]}...")
    
    # Verify the token
    header, claims = jwt.verify_jwt(
        token, 
        key, 
        ['PS256'],  # Only allow PS256 algorithm
        iat_skew=timedelta(seconds=30)  # 30-second clock skew tolerance
    )
    
    print("Token verification successful!")
    print(f"Subject: {claims['sub']}")
    print(f"Issued at: {datetime.utcfromtimestamp(claims['iat'])}")
    print(f"Expires at: {datetime.utcfromtimestamp(claims['exp'])}")
    print(f"Roles: {claims['roles']}")
    
except ValueError as e:
    print(f"Token generation failed: {e}")
except Exception as e:
    print(f"Token verification failed: {e}")

Interoperability

The library is designed for interoperability with other JWT implementations and includes test coverage for compatibility with the jose JavaScript library. Tokens generated by python-jwt can be verified by other JWT libraries and vice versa, as long as they follow the JWT specification.