Skip to main content

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.7.x line; see the changelog for 0.2.0 breaking changes (exception hierarchy), 0.4.0 production-hardening, 0.6.0 security/JWKS hardening, and 0.7.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 |

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.7.0.tar.gz (37.4 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.7.0-cp310-abi3-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.10+Windows x86-64

oxyjwt-0.7.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

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

oxyjwt-0.7.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (682.9 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

oxyjwt-0.7.0-cp310-abi3-macosx_11_0_arm64.whl (1.3 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

oxyjwt-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: oxyjwt-0.7.0.tar.gz
  • Upload date:
  • Size: 37.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for oxyjwt-0.7.0.tar.gz
Algorithm Hash digest
SHA256 ad61848b41008034e922f076fb460e1b3dbb3a551597175ce72afc14237c7b3b
MD5 5564b0962e2e37781f17e0a9f9cc6454
BLAKE2b-256 512c514d467b3eb1fc9372592cfad52d30b42415d3bf417165558895c1e02cb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.7.0-cp310-abi3-win_amd64.whl.

File metadata

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

File hashes

Hashes for oxyjwt-0.7.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 1f97973ce58f1c99ebb94332a7fa957a2a68c6e84012a7eeed0412c279a5e5d2
MD5 4db159a8e80d7feac38e3d2b11fad2e9
BLAKE2b-256 4c1b5c2fe98222be87b1306cd0b5bb4fd1807c6898c90a52624940cc201e4ca1

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.7.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.7.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3118f774915b2444de85435eda01463b37c75a19b2de85a114dade9df1dc9526
MD5 47049bf68e3f76027c0c70be3f81ded0
BLAKE2b-256 66caa2aca744b0e96c5ce657468d31c38fc9a27d4549617e55e0cb1cf4fd8c4b

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.7.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.7.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 428ac944956af4d0a9101d0e52c8f0d6795b35ed0985165860c1004e4064c125
MD5 e5cbbe0b1c760ac045cc406bda2f87e8
BLAKE2b-256 76da7e355e568f481c68803894176733693174e98df6f443a5667679fe14b5af

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.7.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8107fdbd949d9a60a275c7c84bc4bc4b2af7ecec1a62b747d6ee2f6bf94674fe
MD5 52c7a5414ff6e1220780aaf900322fb4
BLAKE2b-256 be5d2bf142ac9ed88ee0f4d41073a6a6bc442a7bdf4f48c03a0a6cb038fd58d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.7.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for oxyjwt-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4f8e71e581e71bebfb42518f249ae25b5bf3919a0db3d559fe671516b7058426
MD5 57f9d22ae31923c438ee080f99aa286f
BLAKE2b-256 350fd87f49b47211c99ba3eeb02f144629564de7da5c2abdb1817362b96303d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for oxyjwt-0.7.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.

Release history Release notifications | RSS feed

This release

0.7.0 This release

6 files

0.6.0

6 files

0.5.0

6 files

0.4.0

6 files

0.3.0

6 files

0.2.0

6 files

0.1.0

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page