Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

tessera logo

Acquire and securely store OAuth2/OIDC tokens in JupyterHub.

PyPI Python License


tessera adds a per-server button in JupyterLab. On click, the user runs an OAuth2/OIDC authorization-code flow (confidential client, PKCE). A JupyterHub Service receives the callback, exchanges the code, and stores the refresh token encrypted at rest. Notebooks then read a fresh access token from the Service on demand. The button is green when a valid refresh token exists, red otherwise. tessera is generic: any OAuth2/OIDC provider is a configuration entry.

tessera is not an Authenticator. It never signs anyone in to JupyterHub: your Hub keeps whatever Authenticator it already uses (PAM, LDAP, OAuth, or any other). tessera runs a separate step after that login, acquiring tokens from external OAuth2/OIDC providers so notebooks can call the APIs those providers protect.

The tessera panel in JupyterLab: one button per declared server, green when a valid refresh token is stored, with token details on demand

How it works

  1. One button per declared server. The panel shows a button for each OAuth server in your configuration, green when a valid refresh token is stored for that user, red otherwise.
  2. A click starts an authorization-code flow with PKCE. The Service generates the state and the PKCE verifier, sends the browser to the provider with the S256 challenge, and keeps the verifier to itself.
  3. The provider calls back to the Service, which validates the state against the flow it started and exchanges the code for tokens. The browser never handles a token.
  4. The refresh token is encrypted at rest, with the encryption key held separately from the database file, so the database on its own reveals nothing.
  5. Notebooks read an access token on demand. The kernel client (get_token("my-idp"), or TESSERA_TOKEN["my-idp"]) fetches a fresh token from the Service on each access. Nothing is cached kernel-side and no token ever sits in an environment variable, so a token revoked at the provider is never served from a stale copy.

Architecture (three surfaces)

Surface Stack Role
Frontend TypeScript/React Per-server status button (green/red), shipped as a prebuilt JupyterLab extension.
Service Python 3.10+ JupyterHub Service exposing /login, /callback, /token; encrypted token store.
Admin CLI Python (Typer) Deployment and ops helpers: config-snippet, init-config, doctor, install-kernel-config.

Install

pip install jupyterhub-tessera

Installing the Python package also ships the prebuilt JupyterLab extension; no manual frontend copy is required.

Project layout

Path What lives there
src/tessera/ Service, admin CLI, kernel client, and the prebuilt lab extension
frontend/src/ TypeScript/React panel sources, with their tests alongside them
tests/ Python test suite (config, flow, store, service, kernel, end to end)
docs/ Sphinx documentation sources

Development

Requirements: Python 3.10+, Node.js 20+.

# Python (use a virtual environment created outside any synced folder)
pip install -e ".[dev]"

# Frontend
npm install
npm run build

Security

A refresh token and a client secret are encrypted at rest, with the encryption key held separately from the database. The frontend never reads, stores, or logs a token; it only consumes a boolean status.

License

MIT, Copyright (c) 2026 Michel TRUONG.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jupyterhub_tessera-1.0.0rc1.tar.gz (733.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jupyterhub_tessera-1.0.0rc1-py3-none-any.whl (88.6 kB view details)

Uploaded Python 3

File details

Details for the file jupyterhub_tessera-1.0.0rc1.tar.gz.

File metadata

  • Download URL: jupyterhub_tessera-1.0.0rc1.tar.gz
  • Upload date:
  • Size: 733.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for jupyterhub_tessera-1.0.0rc1.tar.gz
Algorithm Hash digest
SHA256 40b8ec609ac2e47d6d991a9b9212d89bd122f10db374e06386c3f9bab730ae32
MD5 47f160401ff139cbf73669c316777b80
BLAKE2b-256 22d7c30af0ba82981ddbd23b8eb67e56b0a2d402689fc17efb1e31b109d3cd74

See more details on using hashes here.

Provenance

The following attestation bundles were made for jupyterhub_tessera-1.0.0rc1.tar.gz:

Publisher: ci.yml on KaminoU/jupyterhub-tessera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file jupyterhub_tessera-1.0.0rc1-py3-none-any.whl.

File metadata

File hashes

Hashes for jupyterhub_tessera-1.0.0rc1-py3-none-any.whl
Algorithm Hash digest
SHA256 6462687a212aa02399d662577896525fb5afacd3b9e443e3be388b2c06a6d148
MD5 cb8c2c0339ca0e684107ac0c1ef16c1a
BLAKE2b-256 3f76b34ad3e37f0cb70abe4517e0639d772c8aa0fecd3dbdbde48046cd70d0f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for jupyterhub_tessera-1.0.0rc1-py3-none-any.whl:

Publisher: ci.yml on KaminoU/jupyterhub-tessera

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.0

2 files

This release

1.0.0rc1 This release

2 files

0.0.1

2 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