Synchronous and asynchronous OAuth2/OIDC clients for the Verys auth service.
Project description
Verys Python Client
Synchronous and asynchronous OAuth2/OIDC clients for the Verys auth service.
Features
VerysClient(sync) andAsyncVerysClient(async) with identical APIs- Authorization code flow, with PKCE automatically used for public clients
- Refresh token and token-exchange grants
- Federated external token retrieval
- Typed, documented public surface with a clear exception hierarchy
Installation
uv add verys-py-client
# or
pip install verys-py-client
Requires Python 3.14+.
Quickstart
Confidential client (with a client secret)
from verys_py_client import VerysClient
client = VerysClient(
host="https://app.example.com",
base_url="https://auth.verys.example.com",
client_id="your-client-id",
client_secret="your-client-secret",
scopes=["openid", "profile", "email"],
)
# 1. Redirect the user to the authorization URL.
url, state, nonce, code_verifier = client.create_auth_url()
# Persist `state`, `nonce` (and `code_verifier` for public clients) in the session,
# then redirect the user to `url`.
# 2. Handle the callback (e.g. in a Starlette/FastAPI route).
state, code = VerysClient.handle_callback(request)
# 3. Exchange the code for tokens.
id_token, access_token, refresh_token = client.token_by_code(code, nonce)
Public client (no secret — PKCE)
Construct the client with client_secret=None. create_auth_url() then attaches a
PKCE code_challenge and returns a code_verifier you must persist and pass back to
token_by_code:
client = VerysClient(
host="https://app.example.com",
base_url="https://auth.verys.example.com",
client_id="your-public-client-id",
client_secret=None,
scopes=["openid", "profile"],
)
url, state, nonce, code_verifier = client.create_auth_url()
# ... redirect, then on callback:
id_token, access_token, refresh_token = client.token_by_code(code, nonce, code_verifier)
Other grants
# Refresh an access token.
access_token, refresh_token = client.refresh_access_token(refresh_token)
# Exchange a token for one scoped to another audience.
exchanged = client.token_by_exchange(access_token, audience="https://api.other.example")
# Retrieve federated external tokens.
tokens = client.get_external_tokens(access_token)
one = client.get_external_tokens(access_token, token_id="github")
Async usage
AsyncVerysClient mirrors the sync API; methods are awaitable:
from verys_py_client import AsyncVerysClient
client = AsyncVerysClient(
host="https://app.example.com",
base_url="https://auth.verys.example.com",
client_id="your-client-id",
client_secret="your-client-secret",
scopes=["openid", "profile"],
)
id_token, access_token, refresh_token = await client.token_by_code(code, nonce)
Error handling
All errors derive from Exception; most application-level failures subclass
VerysError, while JWKS/public-key failures form a separate JwksError branch.
| Exception | Raised when |
|---|---|
VerysError |
Base class for client errors |
CallbackError |
The authorization callback reports an error |
MissingCodeError / MissingStateError |
The callback is missing code / state |
TokenError |
A token request fails or a returned token is invalid |
NonceError |
The ID token's nonce does not match |
ExternalReauthError |
A federated token requires re-authorization (401) |
JwksError |
The JWKS document cannot be retrieved |
PublicKeyNotFoundError |
No EdDSA signing key is present in the JWKS |
from verys_py_client import TokenError, NonceError
try:
id_token, access_token, refresh_token = client.token_by_code(code, nonce)
except NonceError:
... # possible replay / mismatched session
except TokenError as e:
... # token request failed
Documentation
API reference is generated with MkDocs + mkdocstrings:
uv run mkdocs serve # live preview at http://127.0.0.1:8000
uv run mkdocs build # render static site to ./site
Development
uv sync # install dependencies (including dev tools)
uv run ruff check . # lint
License
MIT © 2026 Reis McMillan
Project details
Release history Release notifications | RSS feed
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 verys_py_client-0.1.0.tar.gz.
File metadata
- Download URL: verys_py_client-0.1.0.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f1edf3db0dcd467b2847d01b11300cea6811bdd6acbdd30659171321817e23d
|
|
| MD5 |
52d4d8a26b6d73ceefb5cfd57c37f336
|
|
| BLAKE2b-256 |
6cb4f16823b0576ba503549ee5286c6d4fb1afc2b28173f736e6c5bd2570a355
|
Provenance
The following attestation bundles were made for verys_py_client-0.1.0.tar.gz:
Publisher:
publish.yml on Reis-McMillan/verys-py-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verys_py_client-0.1.0.tar.gz -
Subject digest:
0f1edf3db0dcd467b2847d01b11300cea6811bdd6acbdd30659171321817e23d - Sigstore transparency entry: 1931616623
- Sigstore integration time:
-
Permalink:
Reis-McMillan/verys-py-client@233dcd00d8fd89dc0c5e2116ca0c97caf02e784c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Reis-McMillan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@233dcd00d8fd89dc0c5e2116ca0c97caf02e784c -
Trigger Event:
release
-
Statement type:
File details
Details for the file verys_py_client-0.1.0-py3-none-any.whl.
File metadata
- Download URL: verys_py_client-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4afc71d0c9c4053508a38c053c6d0d25e4ce234b3bc29aa0b7b7b9f7308fcd62
|
|
| MD5 |
d8f922b5448b671096a500f35f06d5b9
|
|
| BLAKE2b-256 |
daa2692d888a333374094f78f9d8d3874f6bea0293593b11921ee6f66179914f
|
Provenance
The following attestation bundles were made for verys_py_client-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Reis-McMillan/verys-py-client
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
verys_py_client-0.1.0-py3-none-any.whl -
Subject digest:
4afc71d0c9c4053508a38c053c6d0d25e4ce234b3bc29aa0b7b7b9f7308fcd62 - Sigstore transparency entry: 1931616736
- Sigstore integration time:
-
Permalink:
Reis-McMillan/verys-py-client@233dcd00d8fd89dc0c5e2116ca0c97caf02e784c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Reis-McMillan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@233dcd00d8fd89dc0c5e2116ca0c97caf02e784c -
Trigger Event:
release
-
Statement type: