philiprehberger-jwt-lite
Minimal JWT creation and validation with HMAC and RSA signing.
Installation
pip install philiprehberger-jwt-lite
Usage
from philiprehberger_jwt_lite import create_token, verify_token
token = create_token({"sub": "user123"}, "my-secret")
payload = verify_token(token, "my-secret")
Token Expiration
from philiprehberger_jwt_lite import create_token, verify_token, ExpiredTokenError
token = create_token({"sub": "user123"}, "my-secret", expires_in=3600)
try:
payload = verify_token(token, "my-secret")
except ExpiredTokenError:
print("Token has expired")
Custom Algorithm
from philiprehberger_jwt_lite import create_token, verify_token
token = create_token({"sub": "user123"}, "my-secret", algorithm="HS512")
payload = verify_token(token, "my-secret", algorithm="HS512")
RS256 (RSA) Signing
from philiprehberger_jwt_lite import create_token, verify_token
token = create_token({"sub": "user123"}, private_pem, algorithm="RS256")
payload = verify_token(token, public_pem, algorithm="RS256")
Custom Claims Validation
from philiprehberger_jwt_lite import create_token, verify_token, ClaimValidationError
token = create_token({"sub": "user123", "role": "admin"}, "my-secret")
payload = verify_token(
token,
"my-secret",
validators={"role": lambda r: r == "admin"},
)
Token Refresh
from philiprehberger_jwt_lite import create_token, refresh_token
token = create_token({"sub": "user123"}, "my-secret", expires_in=3600)
new_token = refresh_token(token, "my-secret", extends_by=7200)
JTI Auto-Generation
from philiprehberger_jwt_lite import create_token, decode_token
token = create_token({"sub": "user123"}, "my-secret", include_jti=True)
payload = decode_token(token)
print(payload["jti"]) # e.g. "a1b2c3d4-..."
Token Revocation
from philiprehberger_jwt_lite import create_token, verify_token, TokenRevokedError
revoked: set[str] = set()
token = create_token({"sub": "user123"}, "my-secret", include_jti=True)
# Later, revoke the token by its jti
# revoked.add(jti)
try:
payload = verify_token(token, "my-secret", is_revoked=lambda jti: jti in revoked)
except TokenRevokedError:
print("Token has been revoked")
Decode Header
from philiprehberger_jwt_lite import decode_header
header = decode_header(token)
print(header["alg"]) # "HS256"
Decode Without Verification
from philiprehberger_jwt_lite import decode_unverified
header, payload = decode_unverified(token)
print(header["alg"]) # "HS256"
JWK Set Key Management
from philiprehberger_jwt_lite import JWKSet
jwks = JWKSet()
jwks.add_hmac_key("hmac-1", "my-secret")
jwks.add_rsa_key("rsa-1", private_pem=priv, public_pem=pub)
token = jwks.create_token({"sub": "user123"}, "hmac-1", expires_in=3600)
payload = jwks.verify_token(token)
Clock-skew leeway with nbf and iat
import time
from philiprehberger_jwt_lite import create_token, verify_token
token = create_token(
{"sub": "user123", "nbf": time.time() + 5, "iat": time.time()},
"my-secret",
expires_in=3600,
)
# Without leeway, verification fails because nbf is in the future.
# 30s of tolerance is plenty for typical NTP-drift between servers.
payload = verify_token(token, "my-secret", leeway=30)
API
| Function / Class | Description |
|---|---|
create_token(payload, secret, algorithm, expires_in, include_jti) |
Create a signed JWT token (HS256, HS384, HS512, RS256) |
verify_token(token, secret, algorithm, validators, is_revoked, leeway) |
Verify signature and time claims (exp / nbf / iat honoring leeway), run custom validators, return payload |
refresh_token(token, secret, extends_by, algorithm) |
Verify and re-sign a token with a new expiration |
decode_token(token) |
Decode payload without signature verification |
decode_header(token) |
Decode header without signature verification |
decode_unverified(token) |
Decode header and payload without signature validation |
JWKSet |
Key set for managing multiple named signing keys |
JWKSet.add_hmac_key(kid, secret, algorithm) |
Register an HMAC key in the set |
JWKSet.add_rsa_key(kid, private_pem, public_pem, algorithm) |
Register an RSA key pair in the set |
JWKSet.create_token(payload, kid, expires_in, include_jti) |
Create a token signed with a key from the set |
JWKSet.verify_token(token, validators, is_revoked, leeway) |
Verify a token using the kid in its header (supports leeway for exp / nbf / iat) |
ExpiredTokenError |
Raised when a token's exp claim is in the past |
InvalidTokenError |
Raised when a token is malformed or signature is invalid |
ClaimValidationError |
Raised when a custom claim validator fails (subclass of InvalidTokenError) |
TokenRevokedError |
Raised when a token has been revoked |
Development
pip install -e .
python -m pytest tests/ -v
Support
If you find this project useful:
License
Release files for philiprehberger-jwt-lite 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| philiprehberger_jwt_lite-0.5.0.tar.gz | 195.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| philiprehberger_jwt_lite-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 205.3 kB
Release files / philiprehberger_jwt_lite-0.5.0.tar.gz
| Download URL | philiprehberger_jwt_lite-0.5.0.tar.gz |
|---|---|
| Size | 195.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5d9c86491aa6a43eab666d500a4b3b5032d286b81e374a723796288a098ea55c
|
|
BLAKE2b-256 checksum How to use checksums |
833caec30879dd8ed72dcb010989b7d7d490c873b733ae65253f1555ce74af8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / philiprehberger_jwt_lite-0.5.0-py3-none-any.whl
| Download URL | philiprehberger_jwt_lite-0.5.0-py3-none-any.whl |
|---|---|
| Size | 10.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
95808f87dbe98287bfc99bca4d17ab5f8740772bacbf1222f7881dd6c82deb24
|
|
BLAKE2b-256 checksum How to use checksums |
af2667f7437ea75ee2f64bd720473179e668a1cefe0cea5590c7ec2775cdee27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|