JWCrypto implements the JOSE family on top of pyca/cryptography: JWK and JWK sets, JWS, JWE and JWT. Everything is key-object based — a jwk.JWK built from PEM, JSON or generate() — which makes the key type explicit at every call. It is licensed LGPL-3.0-or-later, which matters if you redistribute modified copies.
Its algorithm coverage is the broadest of the Python JOSE libraries: the HS, RS, PS and ES families, ES256K, EdDSA and the fully specified Ed25519 and Ed448, and in 1.6.1 also ML-DSA-44, ML-DSA-65 and ML-DSA-87 with AKP keys from the post-quantum JOSE draft — all signed and verified in the check, and all on the default allowed list. That default list is the catch: unless you pass algs, any of them is accepted for a matching key, so narrow it to what your issuer actually uses, as the sample does.
Unsigned tokens are refused with Algorithm not allowed unless none is listed, and an HS256 token presented with an EC public JWK fails, because the key type cannot perform HMAC. ES256 refuses a P-384 key with Curve requested is "P-256", but key curve is "P-384". ES256 signatures are the 64-byte raw r‖s form; a DER signature fails with Verification failed for all signatures — check the encoding in the JWT debugger.
Two defaults differ from other libraries. Expiry checks allow 60 seconds of clock skew: a token that expired 57 seconds earlier still validated, one that expired 63 seconds earlier did not — more forgiving than PyJWT or jose, which allow none. And exp is optional: a token without it validated unless check_claims names it.
Build key sets with the JWKS builder and inspect encrypted tokens with the JWE inspector; for ML-DSA keys and signatures, the post-quantum signature playground shows the sizes involved.