JWT libraries are easy to use incorrectly. This page is the checklist to read before using OxyJWT for authentication or authorization.
The allowed algorithm list must come from your configuration, not from the token:
claims = oxyjwt.decode(
token,
verification_key,
algorithms=["RS256"],
audience="api",
issuer="https://auth.example.com",
)Do not do this:
header = oxyjwt.get_unverified_header(token)
claims = oxyjwt.decode(token, key, algorithms=[header["alg"]])The second example trusts attacker-controlled input before verification.
OxyJWT rejects alg="none" in the normal API. Unsecured JWTs are not appropriate for authentication.
A classic JWT vulnerability is accepting an RSA public key as an HMAC secret after an attacker changes the token header from RS256 to HS256.
OxyJWT reduces that risk by:
- requiring
algorithmsindecode; - rejecting mixed key families in one
algorithmslist; - accepting raw
str/byteskeys only for HMAC; - requiring explicit key constructors for RSA, PSS, ECDSA, and EdDSA.
Signature verification only proves that a token was signed by a key. It does not prove that the token was meant for your service.
When your issuer includes aud and iss, validate both:
claims = oxyjwt.decode(
token,
key,
algorithms=["RS256"],
audience="api",
issuer="https://auth.example.com",
)If your app requires exp and sub, say so:
claims = oxyjwt.decode(
token,
key,
algorithms=["HS256"],
require=["exp", "sub"],
)Then validate your own business rules after decoding.
Demo examples use short strings because they are readable. Production HMAC secrets should be high entropy and loaded from a secret manager or environment configuration.
Do not print tokens, private keys, or HMAC secrets in logs.
decode with options["verify_signature"] = False parses the token without verifying the JWS signature. OxyJWT warns with InsecureDecodeWarning.
- Do not use the returned claims for authentication or authorization.
subjectis ignored unlessverify_subisTrue(not the default when the signature is off).requireonly asserts that named claims exist in the parsed JSON, not that they are authentic.
Prefer verified decode with an explicit algorithms allow-list in production.
When you pass a raw str / bytes HMAC secret (or use EncodingKey.from_secret / DecodingKey.from_secret), the Rust core copies the material into a buffer that is zeroized on drop after the jsonwebtoken key object is built. Long-lived EncodingKey / DecodingKey instances still hold signing material inside the library as required for operation; prefer short-lived keys and OS secret stores in production.
OxyJWT rejects compact JWT strings larger than 256 KiB (same order of magnitude as the default JWKS max_bytes cap) with DecodeError before base64 or JSON parsing. This applies to verified decode, decode_unverified, get_unverified_header, and jws_parse_compact. RFC 7797 detached_payload bytes passed to verified decode are capped at the same limit before copy or JSON parsing. Legitimate tokens are far smaller; huge inputs are usually denial-of-service attempts.
get_unverified_header and decode_unverified do not verify the signature and do not validate claims.
Good uses:
- selecting a key by
kidbefore verification; - debugging token shape;
- inspecting tokens in trusted local tooling.
Bad uses:
- deciding whether a request is authenticated;
- trusting
sub,role,aud, oriss; - building the allowed algorithm list from the unverified header.
When keys rotate at your identity provider, fetch JWKS over HTTPS and resolve keys by kid:
client = oxyjwt.PyJWKClient(
"https://auth.example.com/.well-known/jwks.json",
require_https=True,
)
signing_key = client.get_signing_key_from_jwt(
token,
algorithms=["RS256"],
)
claims = oxyjwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
audience="api",
issuer="https://auth.example.com",
)Security practices:
- Pass
algorithmstoget_signing_key_from_jwtso disallowed headeralgvalues are rejected before JWKS HTTP I/O. - Enable
require_httpsfor production JWKS URLs. - Set
max_bytes(default 256 KiB) to cap oversized responses. - Do not disable signature verification after resolving a key;
get_signing_key_from_jwtonly inspects the header to findkid. - Tier-2
cache_keysis off by default; enable only if you understand LRU retention ofPyJWKmaterial in memory.
Full parameter reference: API reference — PyJWKClient. Reporting vulnerabilities: SECURITY.md.
OxyJWT signs and verifies JWT/JWS tokens. It does not encrypt token contents. Anyone who receives a JWT can read its claims unless you use a separate encryption layer.