Auth Providers For Developers¶
This guide explains how CCProxy wires together OAuth providers, token managers, and the developer-facing tooling that interacts with them. Use it as a reference when building a new provider, extending credential flows, or debugging auth issues locally.
Architecture Overview¶
- OAuth providers implement
OAuthProviderProtocoland are registered with the centralOAuthRegistry. Each provider encapsulates the HTTP/OAuth dance (authorization URLs, device flows, refresh logic, revocation) and exposes a storage backend for credentials. - Token managers implement
BaseTokenManager(orEnhancedTokenManager) for provider-specific credential lifecycles. They perform storage I/O, cache data, and surface high-level helper methods used by adapters and the CLI. - Token snapshots (
TokenSnapshot) provide a safe, uniform view of the tokens and metadata the manager currently holds. Snapshots are intentionally lightweight so they can be shared with adapters, CLI commands, and future monitoring endpoints without leaking provider internals. - Adapters, plugins, and CLI commands depend on the snapshot interface
instead of probing credentials with
hasattrchecks. This keeps the call surface consistent across providers.
flowchart LR
subgraph Registry & CLI
CLI[CLI auth commands]
Registry[OAuthRegistry]
end
subgraph Provider Plugin
Provider[OAuth provider]
Manager[Token manager]
Storage[Token storage]
end
CLI -->|discover|get_oauth_provider| Registry --> Provider
Provider -->|load/save| Storage
Provider -->|create_token_manager| Manager
Manager -->|snapshot|get_token_snapshot
CLI -->|render status| Manager
Adapter[HTTP adapter] -->|resolve token| Manager
Provider Responsibilities¶
- Implement the
OAuthProviderProtocolsurface fully. In particular: get_authorization_url,handle_callback, andrefresh_access_tokenmust return provider-specific credential models.get_storage()should return a storage instance (subclassingTokenStorage) ready for read/write operations.get_credential_summary()should leverage snapshots if available to avoid re-implementing masking logic.- Expose factory helpers such as
create_token_manager()when a provider wants to hand back a fully configured token manager to the CLI or services. - Populate
clicapabilities (device flow, browser flow, manual fallback) so the CLI automatically selects the right flow for the environment.
Token Managers & Snapshots¶
- New managers should inherit from
BaseTokenManagerorEnhancedTokenManager. - Override
_build_token_snapshot(...)to map provider models into aTokenSnapshot. At minimum populate: provider: short stable identifier (e.g."claude-api").access_token: raw token string (will be masked by helper methods).refresh_token: optional refresh value.expires_at:datetimedescribing the current access token expiry.scopesandextrasfor provider-specific metadata (plan tier, account type, etc.).- Call
save_credentials()/load_credentials()as usual; the base class now uses snapshots forget_access_token()andget_expiration_time()so your manager implementations stay focused on provider logic. - Use
TokenSnapshot.access_token_preview()when printing to logs or CLI to avoid exposing full secrets.
Snapshot Helper For Non-Manager Contexts¶
The CLI includes _token_snapshot_from_credentials() to convert credential
models into snapshots even when a manager instance is unavailable (for example,
when a provider returns raw credentials but does not hand back a token manager).
If you add a new provider credential model, extend that helper so developers
keep consistent previews in CLI status output.
CLI Usage Patterns¶
ccproxy auth login <provider>discovers the provider via the registry, selects a flow based on the provider's CLI configuration, and stores credentials using the provider's storage implementation.ccproxy auth status <provider>now:- Loads credentials through the provider.
- Attempts to obtain a token manager and request a snapshot.
- Falls back to converting raw credentials into a snapshot if a manager is unavailable.
- Renders profile information, masked token previews, and troubleshooting hints.
ccproxy auth logout <provider>still uses the provider's storage but benefits from the shared snapshot logic when printing diagnostics along the way.
Header Forwarding¶
collect_cli_forward_headers()inccproxy.utils.headerscentralizes the allow/deny logic for CLI-detected headers. Adapters should delegate to this helper instead of duplicating filtering rules.- Detection services expose
get_detected_headers(),get_ignored_headers(), andget_redacted_headers()—the helper respects each list and falls back to the raw header snapshot if a custom implementation raises during filtering. - When forwarding headers, adapters must still block overwriting
authentication-related values (
Authorization,X-API-Key) after merging the helper’s output.
Testing Tips¶
- Unit-test snapshot builders with fixture data to ensure masking, scopes, and
expiry calculations stay stable. See
tests/unit/auth/test_token_snapshots.pyfor examples covering Claude, OpenAI, and Copilot credentials. - When tests rely on
Path.home()(Claude token wrapper reads~/.claude), mock it to avoid interacting with the developer's real credentials. - For end-to-end CLI tests, patch provider factories so that login/status flows return deterministic snapshot data.
Local Development Checklist¶
- Register your provider in the service container so
OAuthRegistrydiscovers it (usually in the plugin'smanifest). - Provide a storage implementation (JSON, database, secrets manager) and wire it into both the provider and token manager constructors.
- Implement
_build_token_snapshotin the manager and update the CLI helper if raw credential conversion is needed. - Add documentation for any provider-specific CLI flags or environment configuration. Development docs should explain how to obtain client IDs, secrets, or mock servers for local testing.
- Run the focused pytest suites under
tests/plugins/<provider>and the shared snapshot tests to confirm behavior before opening a PR.
By following this structure, every auth provider offers a consistent and type-safe surface area for both adapters and developer tooling, making future refactors—such as centralized monitoring or stricter static typing—a drop-in upgrade.