OAuth Integration#
Overview#
Adds OAuth 2.0 support to bfabricPy. The library can now authenticate via PKCE, device code, client credentials, URL tokens, and personal access tokens — in addition to the existing password-based SOAP auth. All OAuth flows are transparent to downstream code: the SOAP engine receives BfabricAuth(login="__oauth__", password=<jwt>) automatically.
New: bfabric._oauth module#
Private module under bfabric/src/bfabric/_oauth/ implementing all OAuth primitives.
File |
Purpose |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
New: Factory methods on Bfabric#
Method |
Grant type |
Use case |
|---|---|---|
|
auto-detect |
Unchanged API. Now auto-detects |
|
client_credentials |
Service accounts / background jobs. |
|
authorization_code + PKCE |
Interactive browser login (programmatic). |
|
device_code |
Headless interactive login (programmatic). |
|
URL token |
Webapps launched from B-Fabric. Returns |
|
URL token + client_credentials |
Dual-identity webapp client. |
New: CLI commands (bfabric-cli auth)#
All commands registered under bfabric-cli auth via cyclopts.
Command |
File |
Description |
|---|---|---|
|
|
Browser-based OAuth login. Caches tokens + writes config. |
|
|
Headless OAuth login. |
|
|
Personal Access Token login. |
|
|
RFC 7591 dynamic client registration. Outputs JSON. |
|
|
Show current auth status for an environment. |
|
|
Clear cached OAuth tokens. |
All auth commands use --config-env (consistent with API commands via @use_client).
auth register enhancements#
--config-envreuses a cached OAuth token from an existing environment (no manual bearer token needed)--config-filespecifies the config file pathbase_urlis optional when--config-envis provided (inferred from config)Token resolution: explicit
--token> cached OAuth token via--config-env> interactive prompt
Config file changes#
New fields in environment config#
PRODUCTION:
base_url: "https://bfabric.example.com/bfabric"
auth_method: "oauth" # NEW — triggers OAuth flow in Bfabric.connect()
client_id: "bfabric-cli" # NEW — optional, defaults to "bfabric-cli"
New: config_writer.py#
write_environment_to_config() — creates or updates a YAML environment section with atomic writes (0o600 permissions). Used by all login commands.
ConfigData / EnvironmentConfig#
Both models gained auth_method and client_id fields. Bfabric.connect() checks auth_method == "oauth" to route to _connect_oauth_from_config().
CLI error handling improvements#
@use_clientdecorator now catchesValueError/RuntimeErrorfromBfabric.connect()and from the wrapped function, printing clean error messages to stderr and exiting with code 1.Removed
@logger.catch(reraise=True)from all API commands (create, read, update, delete, inspect) — error handling is now centralized in@use_client.ResultContainer.assert_success()now formats errors inline ("Query was not successful: Insufficient scope...") instead of passing a tuple.
Dependencies#
authlib— new dependency (added tobfabric/pyproject.toml)httpx— used byregistration.pyfor RFC 7591 HTTP calls
Test coverage#
~1800 lines of new tests across 15 test files covering:
All OAuth flows (PKCE, device code, client credentials, URL token)
Credential provider (token refresh, thread safety, disk caching, cache priority)
Token cache (save/load/clear, path computation, permissions)
Client registration
Webapp client
All 6 CLI auth commands
Config file parsing with new OAuth fields
Config writer
Scope enforcement (server-side)#
B-Fabric now enforces OAuth scopes at the API level:
api:readrequired for SOAP read operationsapi:writerequired for SOAP write operationsAdditional scopes (e.g.
tus,download) can be requested and are enforced by their respective endpoints
The bfabric-cli default client is pre-registered with: openid, profile, email, api:read, api:write, tus, download, offline_access.
How to install from this branch#
# As a library dependency
pip install "bfabric @ git+https://github.com/fgcz/bfabricPy.git@oauth-integration#subdirectory=bfabric"
# As a CLI tool (both packages from branch)
uv tool install \
"bfabric-scripts @ git+https://github.com/fgcz/bfabricPy.git@oauth-integration#subdirectory=bfabric_scripts" \
--with "bfabric @ git+https://github.com/fgcz/bfabricPy.git@oauth-integration#subdirectory=bfabric" \
--reinstall