This release is a pre-release and may not be stable for production use.
Acquire and securely store OAuth2/OIDC tokens in JupyterHub.
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.
How it works
- 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.
- A click starts an authorization-code flow with PKCE. The Service
generates the
stateand the PKCE verifier, sends the browser to the provider with the S256 challenge, and keeps the verifier to itself. - The provider calls back to the Service, which validates the
stateagainst the flow it started and exchanges the code for tokens. The browser never handles a token. - 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.
- Notebooks read an access token on demand. The kernel client
(
get_token("my-idp"), orTESSERA_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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40b8ec609ac2e47d6d991a9b9212d89bd122f10db374e06386c3f9bab730ae32
|
|
| MD5 |
47f160401ff139cbf73669c316777b80
|
|
| BLAKE2b-256 |
22d7c30af0ba82981ddbd23b8eb67e56b0a2d402689fc17efb1e31b109d3cd74
|
Provenance
The following attestation bundles were made for jupyterhub_tessera-1.0.0rc1.tar.gz:
Publisher:
ci.yml on KaminoU/jupyterhub-tessera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jupyterhub_tessera-1.0.0rc1.tar.gz -
Subject digest:
40b8ec609ac2e47d6d991a9b9212d89bd122f10db374e06386c3f9bab730ae32 - Sigstore transparency entry: 2400871186
- Sigstore integration time:
-
Permalink:
KaminoU/jupyterhub-tessera@6ab126a95cf19db6ecc6382c4be79d823de65e4a -
Branch / Tag:
refs/tags/v1.0.0rc1 - Owner: https://github.com/KaminoU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@6ab126a95cf19db6ecc6382c4be79d823de65e4a -
Trigger Event:
push
-
Statement type:
File details
Details for the file jupyterhub_tessera-1.0.0rc1-py3-none-any.whl.
File metadata
- Download URL: jupyterhub_tessera-1.0.0rc1-py3-none-any.whl
- Upload date:
- Size: 88.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6462687a212aa02399d662577896525fb5afacd3b9e443e3be388b2c06a6d148
|
|
| MD5 |
cb8c2c0339ca0e684107ac0c1ef16c1a
|
|
| BLAKE2b-256 |
3f76b34ad3e37f0cb70abe4517e0639d772c8aa0fecd3dbdbde48046cd70d0f4
|
Provenance
The following attestation bundles were made for jupyterhub_tessera-1.0.0rc1-py3-none-any.whl:
Publisher:
ci.yml on KaminoU/jupyterhub-tessera
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jupyterhub_tessera-1.0.0rc1-py3-none-any.whl -
Subject digest:
6462687a212aa02399d662577896525fb5afacd3b9e443e3be388b2c06a6d148 - Sigstore transparency entry: 2400871279
- Sigstore integration time:
-
Permalink:
KaminoU/jupyterhub-tessera@6ab126a95cf19db6ecc6382c4be79d823de65e4a -
Branch / Tag:
refs/tags/v1.0.0rc1 - Owner: https://github.com/KaminoU
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@6ab126a95cf19db6ecc6382c4be79d823de65e4a -
Trigger Event:
push
-
Statement type: