JOSE protocol implementation in Python with support for JSON Web Algorithms, Keys, and Signatures
73
Comprehensive error hierarchy for serialization, deserialization, and cryptographic operation failures with detailed error information for debugging and error recovery.
Root exception class for all JOSE-related errors.
class Error(Exception):
"""
Generic JOSE Error.
Base class for all JOSE-related exceptions. Inherit from this
class when creating custom JOSE error types.
"""Errors that occur during JSON serialization operations.
class SerializationError(Error):
"""
JSON serialization error.
Raised when an object cannot be serialized to JSON format,
typically due to unsupported data types or circular references.
"""Errors that occur during JSON deserialization and data validation.
class DeserializationError(Error):
"""
JSON deserialization error.
Raised when JSON data cannot be parsed or converted to the
expected object type. Common causes include:
- Invalid JSON structure
- Missing required fields
- Type conversion failures
- Size validation failures
"""
def __str__(self) -> str:
"""Returns formatted error message with 'Deserialization error:' prefix"""Specialized deserialization error for unknown or unsupported object types.
class UnrecognizedTypeError(DeserializationError):
"""
Unrecognized type error.
Raised when attempting to deserialize a JSON object with an
unknown or unsupported type identifier.
"""
def __init__(self, typ: str, jobj: Any) -> None:
"""
Initialize with type information.
Parameters:
- typ: The unrecognized type identifier
- jobj: Full JSON object that caused the error
"""
def __str__(self) -> str:
"""Returns detailed error message with type and full object"""
typ: str # The unrecognized type identifier
jobj: Any # Full JSON objectfrom josepy import JWS, JWKRSA, RS256
from josepy.errors import Error, DeserializationError, SerializationError
try:
# Attempt to load invalid JWS
jws = JWS.json_loads('{"invalid": "jws_structure"}')
except DeserializationError as e:
print(f"Failed to parse JWS: {e}")
# Handle invalid input gracefully
try:
# Attempt signature verification with wrong key
payload = jws.verify(wrong_key)
except Error as e:
print(f"Signature verification failed: {e}")
# Handle authentication failurefrom josepy import JWK
from josepy.errors import UnrecognizedTypeError, DeserializationError
# Example JSON with unknown key type
unknown_jwk_json = '''
{
"kty": "unknown_key_type",
"use": "sig",
"n": "...",
"e": "AQAB"
}
'''
try:
jwk = JWK.json_loads(unknown_jwk_json)
except UnrecognizedTypeError as e:
print(f"Unknown key type: {e.typ}")
print(f"Full object: {e.jobj}")
# Could fall back to a different key handling strategy
except DeserializationError as e:
print(f"General deserialization error: {e}")
# Handle other parsing issuesimport json
from josepy import JWKRSA
from josepy.errors import DeserializationError
# Detailed error handling with context
def safe_jwk_load(jwk_data: str) -> Optional[JWKRSA]:
try:
# First validate JSON structure
json_obj = json.loads(jwk_data)
# Then attempt JWK deserialization
return JWKRSA.json_loads(jwk_data)
except json.JSONDecodeError as e:
print(f"Invalid JSON at line {e.lineno}, column {e.colno}: {e.msg}")
return None
except DeserializationError as e:
print(f"JWK deserialization failed: {e}")
print(f"Input data: {jwk_data[:100]}..." if len(jwk_data) > 100 else jwk_data)
return None
except Exception as e:
print(f"Unexpected error: {type(e).__name__}: {e}")
return None
# Usage
jwk = safe_jwk_load(potentially_invalid_jwk_json)
if jwk is None:
print("Failed to load JWK, using default key")
jwk = get_default_key()import cryptography.exceptions
from josepy import RS256, JWKRSA
from josepy.errors import Error
def safe_sign_and_verify(message: bytes, jwk: JWKRSA) -> bool:
try:
# Sign message
signature = RS256.sign(jwk.key, message)
# Verify signature
is_valid = RS256.verify(jwk.public_key().key, message, signature)
return is_valid
except cryptography.exceptions.InvalidSignature:
print("Cryptographic signature operation failed")
return False
except Error as e:
print(f"JOSE operation failed: {e}")
return False
except Exception as e:
print(f"Unexpected error: {e}")
return False
# Usage
success = safe_sign_and_verify(b"test message", my_jwk)
print(f"Signature test: {'PASSED' if success else 'FAILED'}")from josepy import JWK, JWKRSA, JWKEC, JWKOct
from josepy.errors import UnrecognizedTypeError, DeserializationError
def robust_jwk_loader(jwk_json: str) -> Optional[JWK]:
"""
Attempt to load JWK with multiple fallback strategies.
"""
try:
# First try generic JWK loading
return JWK.from_json(json.loads(jwk_json))
except UnrecognizedTypeError as e:
print(f"Unknown key type '{e.typ}', trying specific loaders...")
# Try specific key types as fallbacks
json_obj = e.jobj
if json_obj.get('kty') == 'RSA':
try:
return JWKRSA.from_json(json_obj)
except DeserializationError:
pass
elif json_obj.get('kty') == 'EC':
try:
return JWKEC.from_json(json_obj)
except DeserializationError:
pass
elif json_obj.get('kty') == 'oct':
try:
return JWKOct.from_json(json_obj)
except DeserializationError:
pass
print("All fallback strategies failed")
return None
except DeserializationError as e:
print(f"Deserialization failed: {e}")
return None
# Usage with graceful degradation
jwk = robust_jwk_loader(received_jwk_json)
if jwk is None:
print("Using fallback authentication method")
# Implement alternative authenticationimport logging
from josepy.errors import Error, DeserializationError, SerializationError
# Configure logging for JOSE operations
logger = logging.getLogger('josepy_operations')
def logged_jws_operation(operation_name: str, operation_func, *args, **kwargs):
"""Wrapper for JWS operations with comprehensive logging."""
try:
logger.info(f"Starting {operation_name}")
result = operation_func(*args, **kwargs)
logger.info(f"Successfully completed {operation_name}")
return result
except DeserializationError as e:
logger.error(f"{operation_name} deserialization failed: {e}")
raise
except SerializationError as e:
logger.error(f"{operation_name} serialization failed: {e}")
raise
except Error as e:
logger.error(f"{operation_name} JOSE error: {e}")
raise
except Exception as e:
logger.critical(f"{operation_name} unexpected error: {type(e).__name__}: {e}")
raise
# Usage
try:
jws = logged_jws_operation("JWS creation", JWS.sign, payload, key=jwk, alg=RS256)
verified = logged_jws_operation("JWS verification", jws.verify, public_jwk)
except Error:
# Handle JOSE-specific errors
handle_jose_error()Install with Tessl CLI
npx tessl i tessl/pypi-josepyevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10