Skip to main content

Fulla Python Client

Typed Python SDK for Fulla — the embeddable C++ OAuth2/OIDC authorization server.

  • Distribution name: fulla-oauth2 (the shorter fulla name on PyPI belongs to an unrelated project)
  • Import name: fulla
  • API surface: generated from the server's single-source OpenAPI spec (apps/server/openapi.yaml) with openapi-python-client 0.29.0 — 78 operations, fully typed (py.typed), attrs-based models over httpx
  • Auth layer: handwritten (token lifecycle is too sensitive to template — see the design doc)
pip install fulla-oauth2

Published to PyPI since v1.3.0 (release pipeline's sdk-python job). Prefer the released wheel; a checkout install (pip install clients/python) still works for development.

Quickstart: machine-to-machine (client_credentials)

from fulla import m2m_client
from fulla.generated.api.o_auth_2 import post_oauth2_introspect
from fulla.generated.models.post_oauth_2_introspect_body import PostOauth2IntrospectBody

client = m2m_client(
    "http://localhost:5555",
    client_id="backend-svc",
    client_secret="…",
    scopes=["tokens:read"],
)

# Every request carries a valid Bearer token: fetched lazily, cached,
# refreshed 30 s before expiry, force-refreshed once on a 401.
result = post_oauth2_introspect.sync(
    client=client, body=PostOauth2IntrospectBody(token=some_access_token)
)
print(result.active)

# When done: closes BOTH the API client and the auth layer's token pool
# (closing the generated client alone leaks the token connection pool).
from fulla import close_m2m_client
close_m2m_client(client)

Async is symmetric:

from fulla import async_m2m_client

client = async_m2m_client("http://localhost:5555", "backend-svc", "…", scopes=["tokens:read"])
result = await post_oauth2_introspect.asyncio(client=client, body=body)

One-shot token fetch (scripts, benchmarks):

from fulla import fetch_client_credentials_token

token, expires_in = fetch_client_credentials_token(
    "http://localhost:5555", "backend-svc", "…", ["tokens:read"]
)

Introspect / revoke (client Basic authentication)

/oauth2/introspect and /oauth2/revoke authenticate the calling client, not a user bearer token (RFC 7662 §2.1). Use a client whose every request carries HTTP Basic — confidential clients must use Basic; the server rejects credentials in the body (F-017):

from fulla import basic_auth_client

client = basic_auth_client("http://localhost:5555", "backend-svc", "…")
result = post_oauth2_introspect.sync(client=client, body=PostOauth2IntrospectBody(token=tok))

Authorization-code flow (web apps, with PKCE)

from fulla import AuthorizationCodeFlow, PkcePair

flow = AuthorizationCodeFlow(
    "http://localhost:5555", "my-client", "my-secret",
    redirect_uri="https://my.app/callback", scopes=["openid", "profile"],
)
pkce = PkcePair.generate()
authorize_url = flow.build_authorize_url(state=session_csrf, pkce=pkce)
# → send the user's browser to authorize_url; Fulla redirects back with ?code=…&state=…
# → VERIFY state, then:
tokens = flow.exchange_code(code, pkce.verifier)
# … later; Fulla rotates refresh tokens on every use (V008):
tokens = flow.refresh(tokens.refresh_token)

Generated API modules

Everything under fulla.generated is the typed surface of the whole server API:

from fulla.generated.api.open_id_connect import get_well_known_openid_configuration
from fulla.generated.api.o_auth_2 import get_oauth2_userinfo, post_oauth2_token
from fulla.generated.models.token_request import TokenRequest

Each endpoint module offers sync, sync_detailed, asyncio, asyncio_detailed. The *_detailed variants return status code + raw response alongside the parsed model.

Development

cd clients/python
pip install -e ".[dev]"
pytest                       # unit tests (in-process MockTransport, no server needed)

# integration tests (needs a running full stack, see tests/integration/)
FULLA_BASE_URL=http://127.0.0.1:5555 pytest tests/integration

Regenerating the committed src/fulla/generated/ tree after an openapi.yaml change:

pip install openapi-python-client==0.29.0
python tools/clients/regen_clients.py            # from the repo root

CI (.github/workflows/clients-sdk.yml) re-generates and diffs on every PR touching clients/** or the spec — committed generated code can never go stale.

Versioning

The package version is locked to the server's cmake/Version.cmake (enforced by tools/clients/regen_clients.py --version-only at release time). Breaking HTTP API changes require a major bump on both sides (guarded by the openapi-governance oasdiff workflow).

Local network note

If go/module proxies are unreachable from your network, the Go generator download mentioned in the regen docs needs a GOPROXY mirror (e.g. GOPROXY=https://goproxy.cn,direct). This only affects regenerating clients/go — installing and using this Python package is unaffected.

Download files

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

Source Distribution

fulla_oauth2-1.0.0.tar.gz (58.7 kB view details)

Uploaded Source

Built Distribution

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

fulla_oauth2-1.0.0-py3-none-any.whl (173.7 kB view details)

Uploaded Python 3

File details

Details for the file fulla_oauth2-1.0.0.tar.gz.

File metadata

  • Download URL: fulla_oauth2-1.0.0.tar.gz
  • Upload date:
  • Size: 58.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for fulla_oauth2-1.0.0.tar.gz
Algorithm Hash digest
SHA256 44847de82772e0748fedeca5a95d9171863f8f16c6ac17c76fd1a2af283633fb
MD5 226f3620ed42e749ed8c9119a9968b5c
BLAKE2b-256 6c122fc288d89181130ddd185c02aa1618cfae60325f68a4cad3ac0062651661

See more details on using hashes here.

File details

Details for the file fulla_oauth2-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: fulla_oauth2-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 173.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for fulla_oauth2-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6146087a1138eddb7636e2be91cc9f805276038f85822e7e34fb92722bb0b919
MD5 409e3ba27e89730408e1917e12fd4ffc
BLAKE2b-256 e22292454385ec7ada4da644683f0ec359516a6c36c03507d839606b888a0b9b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page