JSON Web Token implementation in Python with support for JWT, JWS, JWK, and JWKS
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Lower-level JSON Web Signature operations for signing and verifying arbitrary payloads. Provides direct access to the signature layer without JWT-specific claim validation, useful for custom payload formats or when you need fine-grained control over the signature process.
Creates signed JSON Web Signatures from byte payloads with flexible header management and algorithm support.
class PyJWS:
def __init__(self, algorithms: list = None, options: dict = None):
"""
Initialize JWS instance with algorithm whitelist.
Args:
algorithms (list): Allowed algorithms for this instance
options (dict): Default options for verification
"""
def encode(self, payload: bytes, key, algorithm: str = None,
headers: dict = None, json_encoder = None,
is_payload_detached: bool = False, sort_headers: bool = True) -> str:
"""
Create a JWS signature for the given payload.
Args:
payload (bytes): Data to be signed
key: Private key for signing
algorithm (str): Signing algorithm
headers (dict): Additional headers
json_encoder: Custom JSON encoder
is_payload_detached (bool): Create detached signature
sort_headers (bool): Sort header keys
Returns:
str: JWS token
Raises:
InvalidKeyError: Invalid key for algorithm
InvalidAlgorithmError: Unsupported algorithm
"""Usage examples:
import jwt
# Basic JWS encoding
jws = jwt.PyJWS()
payload = b'{"user_id": 123, "role": "admin"}'
token = jws.encode(payload, 'secret', algorithm='HS256')
# With custom headers
headers = {'typ': 'JWT', 'kid': 'key-1'}
token = jws.encode(payload, 'secret', algorithm='HS256', headers=headers)
# Detached payload (payload not included in token)
token = jws.encode(payload, 'secret', algorithm='HS256', is_payload_detached=True)Decodes and verifies JSON Web Signatures returning the raw payload bytes without JWT-specific processing.
class PyJWS:
def decode(self, jws: str | bytes, key = '', algorithms: list = None,
options: dict = None, detached_payload: bytes = None) -> bytes:
"""
Verify JWS signature and return payload.
Args:
jws (str | bytes): JWS token to verify
key: Public key for verification
algorithms (list): Allowed algorithms
options (dict): Verification options
detached_payload (bytes): Payload for detached signatures
Returns:
bytes: Verified payload
Raises:
DecodeError: Token format errors
InvalidSignatureError: Signature verification failed
InvalidAlgorithmError: Algorithm not allowed
"""
def decode_complete(self, jws: str | bytes, key = '', algorithms: list = None,
options: dict = None, detached_payload: bytes = None) -> dict:
"""
Decode JWS returning header, payload, and signature.
Returns:
dict: {'header': dict, 'payload': bytes, 'signature': bytes}
"""Usage examples:
import jwt
from jwt.exceptions import InvalidSignatureError
jws = jwt.PyJWS()
# Basic decoding
try:
payload = jws.decode(token, 'secret', algorithms=['HS256'])
print(f"Payload: {payload.decode('utf-8')}")
except InvalidSignatureError:
print("Signature verification failed")
# With detached payload
payload = jws.decode(token, 'secret', algorithms=['HS256'],
detached_payload=original_payload)
# Get complete structure
decoded = jws.decode_complete(token, 'secret', algorithms=['HS256'])
print(f"Header: {decoded['header']}")
print(f"Payload: {decoded['payload']}")Extract and validate JWT headers without signature verification, useful for determining key IDs or algorithm information.
class PyJWS:
def get_unverified_header(self, jwt: str | bytes) -> dict:
"""
Extract JWT header without signature verification.
Args:
jwt (str | bytes): JWT token
Returns:
dict: JWT header
Raises:
DecodeError: Invalid token format
InvalidTokenError: Invalid header structure
"""Usage example:
import jwt
jws = jwt.PyJWS()
# Extract header to determine key ID
header = jws.get_unverified_header(token)
key_id = header.get('kid')
algorithm = header.get('alg')
print(f"Key ID: {key_id}, Algorithm: {algorithm}")
# Use header info to select appropriate key
if key_id == 'key-1':
key = get_key_1()
elif key_id == 'key-2':
key = get_key_2()
payload = jws.decode(token, key, algorithms=[algorithm])Manage cryptographic algorithms for JWS instances with registration and whitelisting capabilities.
class PyJWS:
def register_algorithm(self, alg_id: str, alg_obj) -> None:
"""
Register a new algorithm for use with this JWS instance.
Args:
alg_id (str): Algorithm identifier
alg_obj: Algorithm implementation
Raises:
ValueError: Algorithm already registered
TypeError: Invalid algorithm object
"""
def unregister_algorithm(self, alg_id: str) -> None:
"""
Remove an algorithm from this JWS instance.
Args:
alg_id (str): Algorithm identifier
Raises:
KeyError: Algorithm not registered
"""
def get_algorithm_by_name(self, alg_name: str):
"""
Get algorithm implementation by name.
Args:
alg_name (str): Algorithm name
Returns:
Algorithm object
Raises:
NotImplementedError: Algorithm not supported
"""
def get_algorithms(self) -> list:
"""
Get list of supported algorithm names.
Returns:
list: Algorithm names
"""Usage example:
import jwt
jws = jwt.PyJWS()
# Check supported algorithms
algorithms = jws.get_algorithms()
print(f"Supported: {algorithms}")
# Get algorithm object
hs256 = jws.get_algorithm_by_name('HS256')
# Register custom algorithm (advanced usage)
from jwt.algorithms import Algorithm
class CustomAlgorithm(Algorithm):
def sign(self, msg, key):
# Custom signing logic
pass
def verify(self, msg, key, sig):
# Custom verification logic
pass
jws.register_algorithm('CUSTOM', CustomAlgorithm())Convenience functions that use a global PyJWS instance:
def get_unverified_header(jwt: str | bytes) -> dict:
"""Extract header without verification (global function)."""
def register_algorithm(alg_id: str, alg_obj) -> None:
"""Register algorithm globally."""
def unregister_algorithm(alg_id: str) -> None:
"""Unregister algorithm globally."""
def get_algorithm_by_name(alg_name: str):
"""Get algorithm by name (global function)."""Usage example:
import jwt
# Using global functions
header = jwt.get_unverified_header(token)
jwt.register_algorithm('CUSTOM', custom_alg)
algorithm = jwt.get_algorithm_by_name('HS256')JWS verification options are simpler than JWT options:
# Default JWS verification options
{
'verify_signature': True # Verify signature
}Usage example:
# Disable signature verification (dangerous!)
options = {'verify_signature': False}
payload = jws.decode(token, options=options)JWS supports detached signatures where the payload is not included in the token:
import jwt
jws = jwt.PyJWS()
payload = b'sensitive data'
# Create detached signature
token = jws.encode(payload, 'secret', algorithm='HS256', is_payload_detached=True)
# Verify with separate payload
verified = jws.decode(token, 'secret', algorithms=['HS256'],
detached_payload=payload)Install with Tessl CLI
npx tessl i tessl/pypi-pyjwt