{"id":882,"library":"joserfc","title":"JOSE RFCs Implementation","description":"joserfc is a Python library that provides a comprehensive implementation of several essential JSON Object Signing and Encryption (JOSE) standards, including JWS, JWE, JWK, JWA, and JWT. It is derived from Authlib, but features a redesigned API specific to JOSE functionality. It strictly follows the latest versions of the JOSE standards, guaranteeing interoperability and compliance. The current version is 1.6.3 and it maintains an active release cadence with regular updates.","status":"active","version":"1.6.3","language":"python","source_language":"en","source_url":"https://github.com/authlib/joserfc","tags":["jwt","jose","jwk","jwe","jws","jwa","security","cryptography","rfc"],"install":[{"cmd":"pip install joserfc","lang":"bash","label":"Install joserfc"}],"dependencies":[{"reason":"Required for cryptographic operations.","package":"cryptography","optional":false}],"imports":[{"symbol":"jwt, jwk","correct":"from joserfc import jwt, jwk"},{"symbol":"RSAKey","correct":"from joserfc.jwk import RSAKey"},{"note":"Deprecated rfc modules were removed in v1.4.0; use the direct jws module instead.","wrong":"from joserfc.rfc7797 import serialize_compact, deserialize_compact","symbol":"serialize_compact, deserialize_compact","correct":"from joserfc.jws import serialize_compact, deserialize_compact"},{"note":"Renamed to BaseClaimsRegistry in v1.4.0.","wrong":"from joserfc.jwt import ClaimsRegistry","symbol":"ClaimsRegistry","correct":"from joserfc.jwt import BaseClaimsRegistry"}],"quickstart":{"code":"import os\nfrom joserfc import jwt, jwk\n\n# For demonstration, use a simple symmetric key. In production, use a secure, generated key.\nsecret_key = os.environ.get('JOSERFC_SECRET_KEY', 'your-super-secret-key-that-is-at-least-32-chars')\n\n# 1. Import or generate a JWK\n# For symmetric keys, use 'oct' (octet) key type\nkey = jwk.import_key(secret_key, 'oct')\n\n# 2. Define JWT header and claims\nheader = {\"alg\": \"HS256\", \"typ\": \"JWT\"}\nclaims = {\"sub\": \"1234567890\", \"name\": \"John Doe\", \"iat\": 1516239022}\n\n# 3. Encode the JWT\nencoded_jwt = jwt.encode(header, claims, key)\nprint(f\"Encoded JWT: {encoded_jwt}\")\n\n# 4. Decode the JWT\ntoken = jwt.decode(encoded_jwt, key)\nprint(f\"Decoded Header: {token.header}\")\nprint(f\"Decoded Claims: {token.claims}\")\n\n# 5. Validate claims (important for production)\nclaims_registry = jwt.JWTClaimsRegistry()\ntry:\n    claims_registry.validate(token.claims, now=1516239022) # 'now' for reproducible example\n    print(\"Claims validated successfully.\")\nexcept jwt.InvalidClaimError as e:\n    print(f\"Claim validation failed: {e}\")","lang":"python","description":"This quickstart demonstrates how to encode and decode a JSON Web Token (JWT) using a symmetric key. It also includes an example of explicit claims validation, which is a crucial step for production environments."},"warnings":[{"fix":"Update import paths and usage to directly use methods from `joserfc.jws`, `joserfc.jwe`, etc. For instance, `joserfc.jws.serialize_compact` instead of `joserfc.rfc7797.serialize_compact`.","message":"The deprecated `joserfc.rfcXXXX` modules (e.g., `joserfc.rfc7797` for JWS compact serialization/deserialization) were removed in favor of direct usage of modules like `joserfc.jws`.","severity":"breaking","affected_versions":">=1.4.0"},{"fix":"Adjust import statements and class instantiations to use `BaseClaimsRegistry`.","message":"`jwt.ClaimsRegistry` was renamed to `jwt.BaseClaimsRegistry`.","severity":"breaking","affected_versions":">=1.4.0"},{"fix":"Review error handling code to catch the new, more specific exception types. Use `InvalidClaimError` for JWT claim validation failures.","message":"Error classes related to JWT claims and JWS/JWE operations have changed significantly. `InvalidTokenError` and `ExpiredTokenError` were deprecated in favor of `InvalidClaimError`, and `ValueError` in JWS/JWE registries was replaced by `UnsupportedAlgorithmError`. Other new specific errors like `MissingKeyTypeError` and `InvalidKeyIdError` were introduced.","severity":"breaking","affected_versions":">=1.4.1, >=1.6.1"},{"fix":"Always perform claims validation explicitly after decoding a token, for example, by creating an instance of `jwt.JWTClaimsRegistry` and calling its `validate` method on the token's claims.","message":"Unlike some other JWT libraries (e.g., `PyJWT`), `joserfc` separates token decoding from claims validation. The `.decode()` method only extracts header and payload; explicit validation using `jwt.JWTClaimsRegistry` is required.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use a third-party HTTP client library like `requests` to retrieve JWK Sets from URLs, then use `jwk.JsonWebKey.import_key_set()` to load them.","message":"`joserfc` does not provide a built-in HTTP client for fetching JWK Sets from a URL (e.g., from an OpenID Connect discovery endpoint).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure you are using sufficiently strong keys (e.g., RSA keys of at least 2048 bits, preferably 4096 bits, and symmetric keys of appropriate length for the chosen algorithm) to avoid these warnings and maintain security.","message":"Security warnings are now shown when importing potentially weak `OctKey` and `RSAKey` instances, typically if the key size is insufficient.","severity":"gotcha","affected_versions":">=1.4.1"}],"env_vars":null,"last_verified":"2026-05-12T20:44:30.112Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Enable the unsupported algorithm manually by passing an `algorithms` parameter to the relevant registry or method (e.g., `jws.serialize_compact`, `jwt.encode`, `jwt.decode`). Example: `jws.serialize_compact(protected, payload, key, algorithms=['HS384'])` or by creating a custom registry.","cause":"By default, joserfc only allows a set of recommended algorithms for security reasons; algorithms like 'HS384' might not be in this default set.","error":"joserfc.errors.UnsupportedAlgorithmError: unsupported_algorithm: Algorithm of \"HS384\" is not recommended"},{"fix":"Pass a custom `JSONEncoder` subclass to the `encoder_cls` parameter of `jwt.encode` to handle the serialization of unsupported data types. For `datetime` objects, `joserfc` automatically converts `iat`, `exp`, and `nbf` to timestamps.","cause":"When using `jwt.encode` to encode claims, the `joserfc` library (which uses Python's `json` module internally) encounters data types like `UUID` or `datetime` that are not natively supported for JSON serialization.","error":"TypeError: Object of type UUID is not JSON serializable"},{"fix":"Ensure that the correct key (e.g., public key for asymmetric algorithms, or the shared secret for symmetric algorithms) is provided for signature verification and that the token has not been altered since it was signed.","cause":"This error indicates that the JWS signature verification failed, typically because the token was tampered with, or an incorrect key was used for verification.","error":"joserfc.errors.BadSignatureError"},{"fix":"Ensure that the JWT includes all claims marked as 'essential' or otherwise required by the `JWTClaimsRegistry` used for validation.","cause":"When validating JWT claims using a `JWTClaimsRegistry`, this error is raised if an 'essential' claim, or any other required claim, is not present in the token's payload.","error":"joserfc.errors.MissingClaimError"},{"fix":"Reduce the size of the JWT's components (header, payload, or signature) to stay within the configured limits. If necessary and after careful security consideration, adjust the `max_header_length`, `max_payload_length`, or `max_signature_length` on the registry used. Also, ensure a robust reverse proxy is in place to cap maximum header sizes.","cause":"This error occurs when the size of the JWT's header, payload, or signature exceeds the predefined maximum length enforced by the `joserfc` library's registry.","error":"joserfc.errors.ExceededSizeError: Header size of 'b''' exceeds 512 bytes."}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"1.6.5","cli_name":"","cli_version":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","installed_version":"1.6.5","pypi_latest":"1.6.5","is_stale":false,"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.33,"mem_mb":6,"disk_size":"35.1M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.34,"mem_mb":5.8,"disk_size":"34.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.6,"import_time_s":0.24,"mem_mb":6,"disk_size":"36M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":5.8,"disk_size":"34M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.58,"mem_mb":6.6,"disk_size":"37.2M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.64,"mem_mb":6.4,"disk_size":"36.1M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.4,"import_time_s":0.57,"mem_mb":6.6,"disk_size":"38M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.49,"mem_mb":6.4,"disk_size":"37M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.43,"mem_mb":6.3,"disk_size":"29.0M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.49,"mem_mb":6.1,"disk_size":"27.9M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.5,"import_time_s":0.48,"mem_mb":6.3,"disk_size":"29M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.52,"mem_mb":6.1,"disk_size":"28M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.4,"mem_mb":6.2,"disk_size":"28.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.42,"mem_mb":6,"disk_size":"27.6M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.1,"import_time_s":0.45,"mem_mb":6.2,"disk_size":"29M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.46,"mem_mb":6,"disk_size":"28M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.31,"mem_mb":6.2,"disk_size":"35.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.31,"mem_mb":6,"disk_size":"34.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3,"import_time_s":0.32,"mem_mb":6,"disk_size":"36M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"joserfc","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.29,"mem_mb":5.8,"disk_size":"35M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}