Skip to main content

A Python JWT library powered by a Rust core.

Project description

OxyJWT

OxyJWT is a Python JWT/JWS library backed by a Rust core. The public API follows PyJWT for encode, decode, decode_complete, JWK/JWKS helpers, and the PyJWKClient. When signature verification is enabled (the default), you must pass an algorithms allow-list, matching common PyJWT usage. Unverified decode is available only when you explicitly set options["verify_signature"] to False (treat the payload as untrusted).

This project is beta software on the 0.5.x line; see the changelog for 0.2.0 breaking changes (exception hierarchy), 0.4.0 production-hardening, and 0.5.0 performance notes.

Documentation

The full documentation is written with MkDocs and lives in docs-site/ as a standalone site:

Build it locally with:

python -m venv .venv
.venv/bin/python -m pip install -U -r docs-site/requirements.txt
.venv/bin/mkdocs serve -f docs-site/mkdocs.yml

Or build a static documentation image for deployment:

docker compose -f docs-site/docker-compose.yml up -d --build

The static site is served on http://127.0.0.1:8001 by default. Point your own reverse proxy at that upstream for HTTPS. Details and OXYJWT_DOCS_PORT are in docs-site/README.md.

Installation

pip install oxyjwt

Requires Python 3.10+. The wheel installs orjson as a runtime dependency (JSON serialization in the Python API layer).

For local development:

python -m venv .venv
.venv/bin/python -m pip install -U pip maturin pytest pytest-cov cryptography pyjwt
.venv/bin/maturin develop --release
.venv/bin/python -m pytest

See RELEASING.md for maintainer release steps.

HMAC Example

import time

import oxyjwt

secret = "super-secret"
payload = {
    "sub": "user-123",
    "role": "admin",
    "aud": "api",
    "iss": "auth-service",
    "exp": int(time.time()) + 3600,
}

token = oxyjwt.encode(payload, secret, algorithm="HS256", headers={"kid": "key-1"})
claims = oxyjwt.decode(
    token,
    secret,
    algorithms=["HS256"],
    audience="api",
    issuer="auth-service",
)

Asymmetric Keys

Use explicit key constructors for RSA, PSS, ECDSA, and EdDSA:

import oxyjwt

signing_key = oxyjwt.EncodingKey.from_rsa_pem(private_pem)
verification_key = oxyjwt.DecodingKey.from_rsa_pem(public_pem)

token = oxyjwt.encode({"sub": "user-123", "exp": 1893456000}, signing_key, algorithm="RS256")
claims = oxyjwt.decode(token, verification_key, algorithms=["RS256"])

Supported algorithms in v1:

  • HS256, HS384, HS512
  • RS256, RS384, RS512
  • PS256, PS384, PS512
  • ES256, ES384
  • EdDSA

Exceptions

OxyJWT exposes a stable exception hierarchy:

try:
    claims = oxyjwt.decode(token, key, algorithms=["HS256"])
except oxyjwt.ExpiredSignatureError:
    ...
except oxyjwt.InvalidTokenError:
    ...

All package exceptions inherit from oxyjwt.OxyJWTError.

Benchmarks

There is a small comparison script for OxyJWT, PyJWT, python-jose, and Authlib:

python -m venv .venv
.venv/bin/python -m pip install -U pip maturin ".[bench]"
.venv/bin/maturin develop --release
.venv/bin/python scripts/compare_jwt_libraries.py \
  --algorithms all \
  --iterations 1000 \
  --rounds 3 \
  --warmup 100 \
  --json benchmark-results/all-algorithms.bench.json \
  --markdown benchmark-results/all-algorithms.bench.md

The script covers HMAC, RSA, RSA-PSS, ECDSA, and EdDSA algorithms. Unsupported library/algorithm combinations are reported as 0 throughput. For a quicker smoke test, pass something like --algorithms HS256,RS256,EdDSA --iterations 100 --rounds 1.

Benchmark fairness: the default --competitor-key-mode pem keeps pre-parsed EncodingKey/DecodingKey for OxyJWT while competitors often receive PEM bytes (see Benchmarks). For asymmetric comparisons, also run with --competitor-key-mode cached.

Benchmark outputs are ignored by git because results depend on the machine, Python version, compiler flags, and CPU state.

The default Rust crypto backend is aws_lc_rs, chosen for stronger performance on RSA and ECDSA in local benchmarks. You can still build with rust_crypto for comparison:

PYO3_BUILD_EXTENSION_MODULE=1 maturin build --release --no-default-features --features rust_crypto

Security Notes

  • Always pass a fixed server-side algorithms list to decode.
  • Never build the algorithms list from untrusted token headers.
  • alg="none" is intentionally unsupported.
  • Raw str/bytes keys are accepted only for HMAC algorithms. Use EncodingKey.from_* and DecodingKey.from_* for RSA, PSS, ECDSA, and EdDSA.
  • Validate audience and issuer for application tokens when those claims are part of your trust model.
  • decode_unverified and get_unverified_header do not authenticate a token. Use them only for inspection/debugging flows, never for authorization.

OxyJWT implements JWT/JWS signing and verification. JWE encryption is not part of the first version.

Contributing and security

See CONTRIBUTING.md for development setup and pull request expectations. Report security issues privately via SECURITY.md.

Performance benchmarks

OxyJWT is optimized for throughput on typical JWT workloads (especially HMAC). See docs-site/docs/benchmarks.md for smoke vs extended vs full workflows and key-preparation modes.

The table below is a historical snapshot (default script settings, pem competitor keys). RS256 encode numbers are not comparable to --competitor-key-mode cached; re-run the script on your hardware before drawing conclusions.

Algorithm Operation OxyJWT PyJWT Authlib python-jose

| HS256 | Encode | 620,270 | 140,670 | 99,408 | 99,507 | | HS256 | Decode | 361,073 | 109,272 | 94,823 | 51,838 | | RS256 | Encode | 1,934 | 35 | 35 | 35 | | RS256 | Decode | 58,752 | 27,200 | 26,085 | 23,046 | | EdDSA | Encode | 69,105 | 17,518 | 15,014 | N/A | | EdDSA | Decode | 31,666 | 10,741 | 10,317 | N/A | | ES256 | Encode | 46,559 | 19,632 | 16,199 | 19,723 |

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oxyjwt-0.5.0.tar.gz (32.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

oxyjwt-0.5.0-cp310-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10+Windows x86-64

oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (814.7 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

oxyjwt-0.5.0-cp310-abi3-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

oxyjwt-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file oxyjwt-0.5.0.tar.gz.

File metadata

  • Download URL: oxyjwt-0.5.0.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oxyjwt-0.5.0.tar.gz
Algorithm Hash digest
SHA256 93c9f6b48aeeb2988c2adbe3d90f19c509bb31e3c9825f27fdac8b35ce70a2cf
MD5 b375f2b9933b0f83c391ecce97fdee6d
BLAKE2b-256 299ce0f5c85d610955e5ea99be3cba83b2e388397e1b1f96020e74a21eff7573

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0.tar.gz:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxyjwt-0.5.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: oxyjwt-0.5.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oxyjwt-0.5.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6ca295e9becc738015b2ab6cb073b062cdf6de3e61dab23d413d50852885bf60
MD5 0639e8065599e54f7940099abf7d2d65
BLAKE2b-256 8c249253a2aa941c186093179040525ab6cde410bcd645a16d63278373620fd8

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b8e6e2391210bdf932b39c6ebc9d3342e5dbbe81c7d5d11221042e8d5062df0e
MD5 42b0dfc6389b20d89478323e9c103bf6
BLAKE2b-256 5cbbbcd66974e2d2d199daba2284d1a01c0d69b6678fa3dc866180ea3801e08a

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1a6a4f36342403418dd7d1db75bd8d2166ff6cabd20d364c3ca22174139a433a
MD5 cb0da3b642faabbfa00e1555920808a2
BLAKE2b-256 7a2dcccdc932a7fee154d60b5b09836a304ae4d31789f1d66179388aed4a7192

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxyjwt-0.5.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aafa65cd93a5984bd447eda36c313d8cc24c0e57dd4e333104a18445c0b80161
MD5 1fbeb393401aafff4a9b2412456665cd
BLAKE2b-256 0248622f62eb0d4275476c0d47d7fecd9274d5abad0719abb4e441547c7192fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file oxyjwt-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 65b062d2228ced8ce82e6830b2d9be97c5fa57b4254f9feb68efa5ae0ed27d30
MD5 e588a5e1565259551209406d19f46a73
BLAKE2b-256 186da144113372df247b0171cfaf0a030c2d425d33b8718fd066f0b5e3e23199

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on QueryaHub/OxyJWT

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page