dbx-tools-auth 0.6.175

Provider-neutral OAuth, credential storage, and locking
Documentation

dbx-tools-auth

Provider-neutral OAuth and persistent credentials for Rust, Node, and Python. The crate owns authorization-code login with PKCE, client-credentials OAuth, refresh-token rotation, rejected-token comparison, and check-lock-check coordination. Databricks-specific profile and endpoint resolution stays in dbx-tools-databricks-auth.

TokenProvider is the Rust acquisition boundary. ProviderOptions exposes a configurable OAuth provider through generated Node and Python bindings: provider name, optional profile, scopes, endpoints, client identity, grant, storage, and timeouts. dbx-tools-google-auth imports this lifecycle and its generated contracts directly.

Shared options and provider implementations

Rust and UniFFI records do not support class inheritance. ProviderOptions.auth and DatabricksAuthOptions.auth compose the same Rust-owned AuthOptions record; the generated Node and Python providers import that record from shared auth. Omit auth to use the defaults: a 30-second lock timeout, a 3600-second login timeout, a 300-second refresh window, and the built-in callback image. Explicit records use AuthOptions::default() in Rust, AuthOptions.create({}) in Node, and AuthOptions() in Python. Node represents the integer seconds as bigint; Python uses int. Negative refresh windows are supported, but an expired token is never reused simply because its refresh window is negative.

use dbx_tools_auth::AuthOptions;

let auth = AuthOptions {
    lock_timeout_seconds: 10,
    ..AuthOptions::default()
};

Rust provider wrappers implement AuthSession::auth_client to inherit login, token lookup, login-policy dispatch, forced refresh, rejected-token comparison, logout, and backend naming. Import AuthSession to call these trait methods. TokenProvider deliberately requires acquisition and refresh implementations: a default refresh that opens a browser would violate noninteractive token lookup. Its safe default is can_authenticate_silently() == false.

CredentialStore::prepare_write defaults to a no-op, while StorageLock::release consumes and drops an RAII lease. Lock acquisition and credential mutation remain required. UniFFI foreign callback interfaces do not inherit Rust default bodies: Node/Python StorageAdapter implementers must provide every method, including an explicit no-op preflight when appropriate.

Credential identity is provider plus optional profile plus the SHA-256 hash of trimmed, deduplicated, sorted scopes. Generic storage defaults to ~/.dbx-tools/auth; the directory can be overridden. FileLayout.Single keeps one versioned token-cache.json and serializes refresh for the entire file. FileLayout.PerCredential keeps one hashed credential directory and token file per identity, with independent refresh locks. File read-modify-write uses a separate short-held lock and atomic replacement. Memory storage retains access tokens only for the current process while using an in-process lock for refresh coordination.

StorageAdapter supports custom persistence without any database dependency. For cross-package use, create a StorageHandle in this package and pass the handle to the provider wrapper. This preserves callback ownership when separate native libraries are loaded. Access-token results never expose refresh tokens; custom storage receives sensitive credential JSON and must protect it. Both create_provider_auth_with_storage and create_persistent_auth_with_storage accept that same handle. Wrap an adapter with create_storage_handle (Node: createStorageHandle) before passing it to either factory.

See the Node and Python packages.