Skip to content

Jotbox

Jotbox is a library for generating and verifying JWTs in python

It provides a common interface for working with purely stateless JWTs or revokable tokens stored in a central whitelist.

Features

  • All JWT encoding and decoding is done using the de-facto standard PyJWT under the hood
  • Optional JWT whitelist for revokable tokens (pluggable storage backend)
  • Redis whitelist support is built in using redis-py
  • Optional idle timeout support to revoke tokens that are not accessed for a given interval
  • Type safe, using generics for an extendable JWT payload model

Install

pip install jotbox

To use the included redis whitelist, you must install redis as well:

pip install redis

Quickstart

import asyncio
import secrets

from jotbox import Jotbox, Payload, JWTDecodeError
from jotbox.whitelist.redis import RedisWhitelist

# Define the payload model
class AccessPayload(Payload):
    user_id: int


# Create our Jotbox instance with some settings
jot = Jotbox[AccessPayload](
    encode_key=secrets.token_hex(),
    payload_type=AccessPayload,
    leeway=10,
    expires_in=7200,  # Expire tokens after 2 hours (optional)
    # Whitelist is optional, skip this if you don't need revoke support
    idle_timeout=600,  # Revoke token after 10 minutes without use
    whitelist=RedisWhitelist("redis://localhost"),
)


async def run():
    # Create a token
    token = await jot.create_token(user_id=42)

    print(token.token)  # the encoded token as string
    # >> eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJkMDFlYmVmNjlk...

    print(repr(token.payload))  # The payload object
    # >> AccessPayload(jti=UUID('d682eabf-...'), iat=1593638317, user_id=42)

    # Verify the encoded token
    payload = await jot.verified_payload(token.token)
    print(payload)
    # >> AccessPayload(jti=UUID('d682eabf-...'), iat=1593638317, user_id=42)

    # revoke the token (logout)
    await jot.revoke_payload(payload)

    try:
        await jot.verified_payload(token.token)
    except JWTDecodeError as e:
        print(repr(e))
        # >> RevokedTokenError('Token ID d682eabf-... has been revoked')


loop = asyncio.get_event_loop()
loop.run_until_complete(run())

See all possible settings in the configuration section