From 61515356a2c2828f4e3d810b10148cf71a5c44da Mon Sep 17 00:00:00 2001 From: Manoj Bajaj Date: Tue, 16 Jun 2026 13:02:11 -0700 Subject: [PATCH] docs: refresh Mintlify site for v0.7 and remove stale profile/library references Align public docs with Principal/Vault/Identity terminology, current daemon API paths, and the CLI/proxy/export integration surface instead of the removed AuthService library API. Co-authored-by: Cursor --- docs/site/changelog.mdx | 66 ++--- docs/site/concepts/provider-registry.mdx | 4 +- docs/site/concepts/proxy-injection.mdx | 2 +- docs/site/concepts/the-daemon.mdx | 2 +- docs/site/guides/custom-providers.mdx | 2 +- docs/site/guides/headless-device-code.mdx | 2 +- docs/site/guides/login-with-oauth.mdx | 2 +- docs/site/guides/multiple-connections.mdx | 9 +- docs/site/installation.mdx | 20 +- .../integrations/agents/anthropic-sdk.mdx | 28 +-- docs/site/integrations/agents/claude-code.mdx | 23 +- docs/site/integrations/agents/codex.mdx | 8 +- docs/site/integrations/agents/cowork.mdx | 39 ++- docs/site/integrations/agents/cursor.mdx | 8 +- docs/site/integrations/agents/hermes.mdx | 12 +- docs/site/integrations/agents/index.mdx | 17 +- docs/site/integrations/agents/langchain.mdx | 32 +-- docs/site/integrations/agents/llamaindex.mdx | 41 +--- docs/site/integrations/agents/nanoclaw.mdx | 32 +-- .../integrations/agents/openai-agents-sdk.mdx | 25 +- docs/site/integrations/agents/opencode.mdx | 8 +- docs/site/integrations/agents/python.mdx | 31 +-- docs/site/integrations/api-key/ahrefs.mdx | 10 +- docs/site/integrations/api-key/apollo.mdx | 10 +- docs/site/integrations/api-key/ashby.mdx | 10 +- docs/site/integrations/api-key/beehiiv.mdx | 10 +- docs/site/integrations/api-key/brevo.mdx | 10 +- docs/site/integrations/api-key/buffer.mdx | 10 +- docs/site/integrations/api-key/calendly.mdx | 10 +- docs/site/integrations/api-key/clearbit.mdx | 10 +- docs/site/integrations/api-key/dub.mdx | 10 +- docs/site/integrations/api-key/g2.mdx | 10 +- docs/site/integrations/api-key/hunter.mdx | 10 +- docs/site/integrations/api-key/index.mdx | 12 +- docs/site/integrations/api-key/instantly.mdx | 10 +- docs/site/integrations/api-key/intercom.mdx | 10 +- .../api-key/keywords-everywhere.mdx | 10 +- docs/site/integrations/api-key/klaviyo.mdx | 10 +- docs/site/integrations/api-key/lemlist.mdx | 10 +- docs/site/integrations/api-key/livestorm.mdx | 10 +- docs/site/integrations/api-key/mailchimp.mdx | 10 +- docs/site/integrations/api-key/mention-me.mdx | 10 +- docs/site/integrations/api-key/openai.mdx | 17 +- docs/site/integrations/api-key/optimizely.mdx | 10 +- docs/site/integrations/api-key/postmark.mdx | 10 +- docs/site/integrations/api-key/resend.mdx | 10 +- docs/site/integrations/api-key/rewardful.mdx | 10 +- docs/site/integrations/api-key/savvycal.mdx | 10 +- docs/site/integrations/api-key/semrush.mdx | 10 +- docs/site/integrations/api-key/sendgrid.mdx | 10 +- docs/site/integrations/api-key/tolt.mdx | 10 +- docs/site/integrations/api-key/typeform.mdx | 10 +- docs/site/integrations/api-key/wistia.mdx | 10 +- docs/site/integrations/api-key/zapier.mdx | 10 +- docs/site/integrations/oauth/atlassian.mdx | 11 +- docs/site/integrations/oauth/discord.mdx | 11 +- docs/site/integrations/oauth/github.mdx | 20 +- docs/site/integrations/oauth/gitlab.mdx | 11 +- docs/site/integrations/oauth/google.mdx | 11 +- docs/site/integrations/oauth/hubspot.mdx | 11 +- docs/site/integrations/oauth/index.mdx | 2 - .../site/integrations/oauth/klaviyo-oauth.mdx | 11 +- docs/site/integrations/oauth/linear.mdx | 11 +- docs/site/integrations/oauth/microsoft.mdx | 11 +- docs/site/integrations/oauth/notion-dcr.mdx | 11 +- docs/site/integrations/oauth/notion.mdx | 11 +- docs/site/integrations/oauth/postiz.mdx | 9 +- docs/site/integrations/oauth/slack.mdx | 11 +- docs/site/integrations/oauth/x.mdx | 11 +- docs/site/quickstart.mdx | 8 +- docs/site/reference/daemon-api.mdx | 129 +++++----- docs/site/reference/python-library.mdx | 228 +++++------------- docs/site/troubleshooting/auth-errors.mdx | 4 +- docs/site/troubleshooting/daemon-issues.mdx | 1 - docs/site/troubleshooting/doctor.mdx | 61 ++--- docs/site/troubleshooting/token-refresh.mdx | 4 +- 76 files changed, 393 insertions(+), 947 deletions(-) diff --git a/docs/site/changelog.mdx b/docs/site/changelog.mdx index c64679ff..8e76f3ef 100644 --- a/docs/site/changelog.mdx +++ b/docs/site/changelog.mdx @@ -8,56 +8,66 @@ keywords: ["authsome changelog", "authsome release notes", "authsome version his A curated summary of authsome releases. For the full per-commit log, see [CHANGELOG.md](https://github.com/agentrhq/authsome/blob/main/CHANGELOG.md) in the repository. - - **Admin audit dashboard.** The local daemon serves an interactive audit dashboard. + + **Documentation refresh.** Public Mintlify docs updated for the Principal / Vault / Identity model. Retired profile-based terminology, removed references to the old in-process `AuthService` library API, and aligned installation, doctor, and daemon API pages with the current storage layout. - **Browser SSO.** Support for browser SSO via Chrome cookie reading. - - **Customizable home directory.** `AUTHSOME_HOME` overrides the default `~/.authsome/` location. Useful for per-project credential isolation and CI. + **Current integration surface.** CLI commands, `authsome run` proxy injection, `authsome export`, and the daemon HTTP API (with PoP JWT auth) are the supported paths for agents and tooling. + - **Notion DCR provider.** Added `notion_dcr` (Dynamic Client Registration) variant for the MCP endpoint at `mcp.notion.com`. + + **Next.js dashboard.** Static dashboard served from the daemon root with provider and connection management UI. - **Improved error handling.** Custom error propagation between the daemon server and CLI client. + **Self-hosting.** Docker Compose setup and self-hosting guide for running the daemon outside a laptop. - **Non-interactive register.** New `--yes` flag on `authsome register` skips the confirmation prompt in scripts. + **Provider expansion.** Bundled providers for Google Workspace services, Jira, Confluence, YouTube, Vertex AI, Todoist, Cloudflare, Outlook, Word, Calendar, Zoom, Reddit, and more. - **Distinct exit code for cancelled credential entry** (exit code 8) so scripts can distinguish user cancellation from authentication failure. + **Architecture cleanup.** Multi-server-compatible identities, cleaner UI auth flows, and client/server home directory split (`~/.authsome/client/` vs `~/.authsome/server/`). - - Documentation pass. Added demo video to README. - + + ⚠ **Breaking:** Principal claim flow required for vault access. Existing local installs must register a Principal and accept the identity claim. - - **Audit logging.** Structured JSON event log written to `~/.authsome/audit.log` for every significant action (login, logout, revoke, export, register). See [Audit log format](/reference/audit-log). + ⚠ **Breaking:** Vault encryption moved to Argon2id KEK/DEK model. Fernet-encrypted vaults cannot be read back; re-login required. - **List output rendered as a table.** `authsome list` shows providers, source (bundled / custom), auth type, default connection, and status in a single tabular view. + **Audit events and principal roles.** Structured audit logging with admin/user roles. Admin audit dashboard. - **Expanded `whoami` context.** Reports the home directory, encryption mode, registered identity handle, and DID. + **Browser SSO.** Chrome cookie reading for providers that support it. - **Regex proxy host URLs.** Provider definitions can declare `api_url: "regex:..."` to match multiple hosts behind a single provider (used by Google and Linear). + **Anthropic and Gemini** bundled providers added. - - Fix: set connection `api_url` directly from the resolved provider definition. + + ⚠ **Breaking:** Principal, Vault, and Identity replace the old profile model. Credentials are namespaced under `vault::...`. See [Principal, Vault, and Identity](/concepts/principal-vault-identity). + + **Claim flow.** Identities must claim a Principal before accessing credentials. + + **Master key rotation.** `rekey` command and API endpoint. + + **CLI restructure.** Provider and admin command namespaces. - - **Architectural restructure.** Vault and AuthLayer split into separate layers with a documented protocol boundary. Public Python API consolidated around `AuthService` and `AuthLayer` (re-exported from the top-level `authsome` package). CLI commands and flags are unchanged. See [Architecture](/concepts/architecture). + + **Configurable proxy scope.** `connected_allow` and related proxy modes in client config. + + **Health checks.** Readiness validates connections for the active identity. + + **Telemetry.** Opt-out PostHog analytics via environment variables. + - **Browser bridge for sensitive input.** OAuth `client_secret` and API keys are now collected through a local browser form (or `getpass` fallback). Sensitive values are no longer accepted as command-line arguments. + + **Browser bridge for sensitive input.** OAuth `client_secret` and API keys collected through a local browser form. - **`{base_url}` templating.** Multi-tenant providers (GitHub Enterprise, Okta, GitLab self-managed) declare a default `base_url` and `--base-url` overrides it at login time. See [Custom providers](/guides/custom-providers#multi-tenant-providers). + **`{base_url}` templating.** Multi-tenant providers (GitHub Enterprise, Okta, GitLab self-managed). - **`--verbose` and `--log-file` flags.** loguru-backed file logging with `--verbose` for DEBUG to stderr. + **Audit logging.** Structured JSON event log for login, logout, revoke, and export. - **mitmproxy CA injection.** Subprocesses started by `authsome run` get a combined system + mitmproxy CA bundle so SDKs trust the proxy by default. + **Admin audit dashboard** and **Notion DCR** provider. - ⚠ **Breaking:** the older `AuthClient` entry point is gone. Library users should switch to `from authsome.server.dependencies import create_auth_service`. See [Python library](/reference/python-library). + **`AUTHSOME_HOME`** for per-project credential isolation. - Initial public series. Established the CLI surface (`login`, `logout`, `revoke`, `remove`, `list`, `inspect`, `get`, `export`, `run`, `register`, `doctor`, `whoami`), the four flow types (PKCE, device code, DCR + PKCE, API key), and the bundled provider set. Major additions in this series include the proxy runner, RC publishing, OAuth scope support, the `--force` flag, and several bundled-provider additions (Ashby, Klaviyo, and others). + Initial public series. Established the CLI surface, four flow types (PKCE, device code, DCR + PKCE, API key), bundled providers, and the proxy runner. ## Versioning @@ -79,7 +89,7 @@ pip install --upgrade authsome uvx authsome@latest --version ``` -Stored credentials, providers, and `config.json` persist across upgrades. The `schema_version` field in `~/.authsome/config.json` and on every `ConnectionRecord` is reserved for forward-compatibility migrations. +Stored credentials, providers, and client config persist across upgrades. Connection records carry a `schema_version` field reserved for forward-compatibility migrations. ## What's next diff --git a/docs/site/concepts/provider-registry.mdx b/docs/site/concepts/provider-registry.mdx index 9a1972fd..3a811a12 100644 --- a/docs/site/concepts/provider-registry.mdx +++ b/docs/site/concepts/provider-registry.mdx @@ -46,7 +46,7 @@ For full templates and the field-by-field schema. For a worked OAuth example usi ## Bundled providers do not imply bundled credentials -A bundled provider definition only describes how to talk to a service. It does not include OAuth client credentials. The first time you log in to an OAuth2 provider, authsome collects your `client_id` and `client_secret` through a secure browser bridge and stores them encrypted in your profile. +A bundled provider definition only describes how to talk to a service. It does not include OAuth client credentials. The first time you log in to an OAuth2 provider, authsome collects your `client_id` and `client_secret` through a secure browser bridge and stores them encrypted in your vault. For services that support Dynamic Client Registration (DCR), the `dcr_pkce` flow registers a fresh OAuth client automatically, no `client_id` collection needed. @@ -64,7 +64,7 @@ For services where the base URL varies per deployment (GitHub Enterprise, Okta, } ``` -During `authsome login`, the user is prompted for the base URL with the JSON value as the default. A custom base URL is saved to the profile and used for all future token refreshes on that connection. +During `authsome login`, the user is prompted for the base URL with the JSON value as the default. A custom base URL is saved to the vault and used for all future token refreshes on that connection. ## Adding your own providers diff --git a/docs/site/concepts/proxy-injection.mdx b/docs/site/concepts/proxy-injection.mdx index f640cdbe..05975aaf 100644 --- a/docs/site/concepts/proxy-injection.mdx +++ b/docs/site/concepts/proxy-injection.mdx @@ -20,7 +20,7 @@ The child process never sees the raw secret. When the child makes an HTTP(S) call, mitmproxy decrypts and inspects the request. It looks at the destination host. - Authsome iterates the registered providers and matches the request host against each provider's `api_url` field. On a match, it asks the AuthLayer for fresh credentials (refreshing if necessary) and injects the right `Authorization` header. + Authsome iterates the registered providers and matches the request host against each provider's `api_url` field. On a match, it asks the daemon for fresh credentials (refreshing if necessary) and injects the right `Authorization` header. The authenticated request goes to the external API. The response streams back through the proxy unchanged. diff --git a/docs/site/concepts/the-daemon.mdx b/docs/site/concepts/the-daemon.mdx index 1ed50aa2..cf736e87 100644 --- a/docs/site/concepts/the-daemon.mdx +++ b/docs/site/concepts/the-daemon.mdx @@ -16,7 +16,7 @@ Authentication flows hold state. They involve asynchronous steps like browser re - **Session state:** Multi-step operations and token refresh logic need a place to live. - **Secure injection:** The proxy needs an isolated component to fetch fresh tokens without exposing the Vault decryption keys to the proxy process itself. -The daemon solves this. It runs a persistent, in-memory coordinator that manages browser bridges, handles OAuth callbacks, serves the dashboard, and orchestrates the Vault and Auth layers. +The daemon solves this. It runs a persistent coordinator that manages browser bridges, handles OAuth callbacks, serves the dashboard, and orchestrates vault access and credential lifecycle. ## Trust boundary and authorization diff --git a/docs/site/guides/custom-providers.mdx b/docs/site/guides/custom-providers.mdx index e310840f..b4357cac 100644 --- a/docs/site/guides/custom-providers.mdx +++ b/docs/site/guides/custom-providers.mdx @@ -169,7 +169,7 @@ authsome login acmecrm authsome get acmecrm --field status # → connected ``` -For OAuth2 providers without DCR, authsome opens a local browser form on first login to collect `client_id` and `client_secret`. They are stored encrypted under the active profile and reused on every subsequent login. They are never accepted as command-line arguments. +For OAuth2 providers without DCR, authsome opens a local browser form on first login to collect `client_id` and `client_secret`. They are stored encrypted in the active vault and reused on every subsequent login. They are never accepted as command-line arguments. ## Multi-tenant providers diff --git a/docs/site/guides/headless-device-code.mdx b/docs/site/guides/headless-device-code.mdx index 1fbadb92..4d81f62e 100644 --- a/docs/site/guides/headless-device-code.mdx +++ b/docs/site/guides/headless-device-code.mdx @@ -68,7 +68,7 @@ In CI, you can capture the authorization URL and code from the command output an authsome login github --flow device_code 2>&1 | tee login.log ``` -The login command waits until the device flow either completes, expires, or is cancelled. For unattended CI you typically log in once on a developer machine and then commit the encrypted profile (or, more often, run the agent only on machines that already have an authenticated profile). +The login command waits until the device flow either completes, expires, or is cancelled. For unattended CI you typically log in once on a developer machine and then copy the encrypted vault data (or, more often, run the agent only on machines that already have an authenticated vault). ## API key providers diff --git a/docs/site/guides/login-with-oauth.mdx b/docs/site/guides/login-with-oauth.mdx index 068d4993..a05e6b7a 100644 --- a/docs/site/guides/login-with-oauth.mdx +++ b/docs/site/guides/login-with-oauth.mdx @@ -52,7 +52,7 @@ This is what happens: - Authsome opens a local form at `http://127.0.0.1:7998`. Paste your `client_id` and `client_secret`. They are encrypted and stored under your profile, then reused on every subsequent login. + Authsome opens a local form at `http://127.0.0.1:7998`. Paste your `client_id` and `client_secret`. They are encrypted and stored in your vault, then reused on every subsequent login. A second browser window opens to the provider's authorization page. Approve the requested scopes. diff --git a/docs/site/guides/multiple-connections.mdx b/docs/site/guides/multiple-connections.mdx index 983825ce..1a0f233f 100644 --- a/docs/site/guides/multiple-connections.mdx +++ b/docs/site/guides/multiple-connections.mdx @@ -66,13 +66,10 @@ authsome login github --connection work --force authsome run -- python my_agent.py ``` -Or use the library, which accepts `connection=` directly: +Or export credentials for a specific connection: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("github", connection="work") +```bash +eval "$(authsome export github --connection work --format env)" ``` ## Remove a connection diff --git a/docs/site/installation.mdx b/docs/site/installation.mdx index eaebaf15..24e5d077 100644 --- a/docs/site/installation.mdx +++ b/docs/site/installation.mdx @@ -49,7 +49,7 @@ Authsome runs on Python 3.13 or newer. It ships as a single PyPI package with no Pin a version: ```bash - uvx authsome@0.2.4 --version + uvx authsome@0.7 --version ``` Use `uvx` when you don't want a persistent install (sandboxed environments, one-off scripts). Every command shown in the rest of the docs as `authsome ` works as `uvx authsome@latest ` here. @@ -87,15 +87,16 @@ On `authsome init`, authsome initializes its home directory at `~/.authsome/`, c ```text ~/.authsome/ - config.json - audit.log - identities/.json - identities/.key + client/ + config.json active identity, proxy mode + logs/authsome.log + identities/.json + identities/.key server/ master.key mode 0600 - kv_store/ - identity_registry.json - daemon/ + authsome.db identity/principal/vault registries + kv_store/ encrypted credential blobs + logs/authsome.log ``` On a fresh `init`, authsome resolves the master key source in this order: @@ -113,7 +114,6 @@ export AUTHSOME_HOME=/var/lib/authsome authsome init ``` - ## Choose the encryption backend By default, authsome uses `encryption.mode = "auto"` and applies the precedence above. To pin the daemon to the local file or OS keychain instead, edit the Authsome config: @@ -129,7 +129,7 @@ By default, authsome uses `encryption.mode = "auto"` and applies the precedence Re-run `authsome doctor` to confirm the backend is reachable. The trade-offs are covered in [Encryption at rest](/security/encryption). -Older installs that used the implicit `default` profile must run `authsome init` again. This release does not migrate credentials under old `profile:default:*` keys. +Upgrading from releases before 0.4 (the old profile model) requires a fresh `authsome init` and re-login. Credentials under `profile:*` keys are not migrated automatically. See [Changelog](/changelog). ## Optional: trust the proxy CA diff --git a/docs/site/integrations/agents/anthropic-sdk.mdx b/docs/site/integrations/agents/anthropic-sdk.mdx index b340e3bf..047fe464 100644 --- a/docs/site/integrations/agents/anthropic-sdk.mdx +++ b/docs/site/integrations/agents/anthropic-sdk.mdx @@ -49,21 +49,20 @@ authsome run -- python my_agent.py The SDK initializes with `ANTHROPIC_API_KEY=authsome-proxy-managed`. Outbound requests to `api.anthropic.com` are intercepted and authenticated at the proxy layer. -## Alternative: pass the key explicitly +## Alternative: export into the environment + +```bash +eval "$(authsome export anthropic --format env)" +python my_agent.py +``` + +Or read the key in Python after export: ```python -from authsome.server.dependencies import create_auth_service +import os from anthropic import Anthropic -auth = create_auth_service() -client = Anthropic(api_key=auth.get_access_token("anthropic")) - -resp = client.messages.create( - model="claude-sonnet-4-5", - max_tokens=1024, - messages=[{"role": "user", "content": "ping"}], -) -print(resp.content[0].text) +client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"]) ``` ## Multi-account workflows @@ -73,11 +72,8 @@ authsome login anthropic --connection personal authsome login anthropic --connection team ``` -In code: - -```python -key = auth.get_access_token("anthropic", connection="team") -client = Anthropic(api_key=key) +```bash +eval "$(authsome export anthropic --connection team --format env)" ``` ## What's next diff --git a/docs/site/integrations/agents/claude-code.mdx b/docs/site/integrations/agents/claude-code.mdx index 38cd18be..32bd8723 100644 --- a/docs/site/integrations/agents/claude-code.mdx +++ b/docs/site/integrations/agents/claude-code.mdx @@ -106,26 +106,20 @@ Without authsome, agents inside Claude Code typically read tokens from environme `authsome run` is the recommended pattern for any Claude Code agent that calls third-party APIs. The child process never sees the real secret because the proxy injects headers at request time. -## Embedding the library +## Export when the proxy is not enough -If you're orchestrating Claude Code from a larger Python program and want to inject credentials before launching Claude, you can drop below the skill into the library: - -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("github", connection="default") - -# pass `token` to your client of choice +```bash +eval "$(authsome export github --connection default --format env)" +python my_agent.py ``` -Or use the proxy without library access: +Or use the proxy without exporting: ```bash authsome run -- python my_agent.py ``` -The library is documented in [Python library reference](/reference/python-library). +See [Python library reference](/reference/python-library) for the daemon HTTP API. ## Multi-account workflows @@ -153,7 +147,6 @@ Claude runs: authsome get github --connection work --field access_token --show-secret ``` - ## What the skill cannot do - **It cannot type a `client_secret` for you.** Authsome refuses sensitive values as command-line arguments. The browser bridge is the only path. @@ -166,7 +159,7 @@ If a Claude-driven login hangs: - Run `authsome doctor` directly from the terminal to surface initialization errors. - Run `authsome --verbose login ` to see the full flow including the daemon round-trips. -- Check `~/.authsome/audit.log` for the most recent action and outcome. +- Run `authsome log` to inspect recent audit events from the daemon. For provider-specific errors, see [OAuth callbacks](/troubleshooting/oauth-callbacks) and [Token refresh](/troubleshooting/token-refresh). @@ -177,7 +170,7 @@ For provider-specific errors, see [OAuth callbacks](/troubleshooting/oauth-callb The proxy injection model the skill uses under the hood. - Drop below the skill into `AuthService` for fine-grained control. + Use `authsome export` or the daemon HTTP API when the proxy is not enough. Every service Claude can log you into out of the box. diff --git a/docs/site/integrations/agents/codex.mdx b/docs/site/integrations/agents/codex.mdx index 40ed95cb..85582ae3 100644 --- a/docs/site/integrations/agents/codex.mdx +++ b/docs/site/integrations/agents/codex.mdx @@ -74,11 +74,9 @@ The proxy uses each provider's default connection. To target a non-default conne If you're orchestrating Codex from a larger Python program and need explicit per-call control, drop below the proxy into the library: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("openai", connection="default") +```bash +authsome run -- python my_agent.py +# or: eval "$(authsome export --format env)" ``` This pattern is cleaner than passing keys through prompts or hardcoding them into `.env` files. See [Python library](/reference/python-library). diff --git a/docs/site/integrations/agents/cowork.mdx b/docs/site/integrations/agents/cowork.mdx index 873d2050..99ad84ce 100644 --- a/docs/site/integrations/agents/cowork.mdx +++ b/docs/site/integrations/agents/cowork.mdx @@ -1,34 +1,28 @@ --- title: "Cowork" sidebarTitle: "Cowork" -description: "Run multi-agent Cowork workflows with per-agent credential isolation using authsome profiles." +description: "Run multi-agent Cowork workflows with per-agent credential isolation using separate AUTHSOME_HOME directories." icon: "users" -keywords: ["cowork authsome", "multi-agent credentials", "per-agent profile", "cowork github oauth"] +keywords: ["cowork authsome", "multi-agent credentials", "AUTHSOME_HOME isolation", "cowork github oauth"] --- -Cowork is a multi-agent runtime that supervises several agents running concurrently. Authsome pairs naturally: give each agent its own profile so credentials never bleed between roles. +Cowork is a multi-agent runtime that supervises several agents running concurrently. Authsome pairs naturally: give each agent role its own `AUTHSOME_HOME` so credentials never bleed between roles. -## Per-agent profiles +## Per-agent isolation + +Use a separate home directory per agent role. Each home gets its own identity, vault, daemon, and audit log. ```bash -# create profiles for each agent role (programmatic; see below) -# then login with the right home dir for each +AUTHSOME_HOME=~/.authsome-pr-bot authsome init +AUTHSOME_HOME=~/.authsome-reviewer authsome init + AUTHSOME_HOME=~/.authsome-pr-bot authsome login github AUTHSOME_HOME=~/.authsome-reviewer authsome login github --connection read ``` -Each profile has its own vault file, own audit log, own master-key access. An agent running with `AUTHSOME_HOME=~/.authsome-pr-bot` cannot reach credentials in `~/.authsome-reviewer`. - -To create named profiles inside a single `AUTHSOME_HOME`: - -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -auth.create_profile("pr-bot", description="Auto-PR agent") -auth.create_profile("reviewer", description="Code review agent") -``` +An agent running with `AUTHSOME_HOME=~/.authsome-pr-bot` cannot reach credentials in `~/.authsome-reviewer`. +For multiple accounts on the same provider within one role, use [multiple connections](/guides/multiple-connections) inside a single home instead of splitting homes. ## Run each agent under its own proxy @@ -40,18 +34,17 @@ AUTHSOME_HOME=~/.authsome-reviewer \ authsome run -- python reviewer.py ``` -Each agent's HTTP_PROXY points at a different daemon instance, each backed by a different vault. The agents cannot read each other's credentials even if one is compromised. +Each agent's `HTTP_PROXY` points at its own daemon instance, each backed by a different vault. The agents cannot read each other's credentials even if one is compromised. ## Multi-agent best practices -- **One profile per role**, not one per developer. A developer with two agents should still have two profiles. -- **Audit each profile separately.** `audit.log` is per-`AUTHSOME_HOME`. Logging is easy to forward. -- **Rotate after compromise of one agent only.** Other profiles are unaffected. +- **One home directory per role**, not one per developer. A developer with two agents should still use two homes. +- **Audit each home separately.** Audit events are scoped to the daemon backing that home. +- **Rotate after compromise of one agent only.** Other homes are unaffected. ## Troubleshooting | Symptom | Fix | |---------|-----| | Two agents accidentally share credentials | They're using the same `AUTHSOME_HOME`. Split them. | -| Port 7998 conflicts | Each `AUTHSOME_HOME` starts its own daemon on its own ephemeral port. Confirm with `lsof -i`. | - +| Port 7998 conflicts | Only one daemon can bind the default port per machine. Use separate hosts, containers, or configure a non-default port for secondary homes. | diff --git a/docs/site/integrations/agents/cursor.mdx b/docs/site/integrations/agents/cursor.mdx index 4779f43e..ec7ac9a9 100644 --- a/docs/site/integrations/agents/cursor.mdx +++ b/docs/site/integrations/agents/cursor.mdx @@ -59,11 +59,9 @@ The MCP server runs behind the proxy. Any third-party API calls it makes use aut If you're driving Cursor from a Python orchestrator, or running inline Python tasks that need explicit credential control, drop below the proxy: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("github", connection="default") +```bash +authsome run -- python my_agent.py +# or: eval "$(authsome export --format env)" ``` See [Python library](/reference/python-library). diff --git a/docs/site/integrations/agents/hermes.mdx b/docs/site/integrations/agents/hermes.mdx index 615236e7..d9c2858c 100644 --- a/docs/site/integrations/agents/hermes.mdx +++ b/docs/site/integrations/agents/hermes.mdx @@ -123,11 +123,9 @@ authsome run -- python my_agent.py Hermes can also drop below the CLI into the Python library when it needs explicit per-call control: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -github_token = auth.get_access_token("github") +```bash +authsome run -- python my_agent.py +# or: eval "$(authsome export --format env)" ``` See [Run agents with the proxy](/guides/run-agents-with-proxy) and [Python library](/reference/python-library) for the full surface. @@ -144,7 +142,7 @@ If a Hermes-driven login hangs: - Run `authsome doctor` directly from the terminal to surface initialization errors. - Run `authsome --verbose login ` to see the full flow including the daemon round-trips. -- Check `~/.authsome/audit.log` for the most recent action and outcome. +- Run `authsome log` to inspect recent audit events from the daemon. For provider-specific errors, see [OAuth callbacks](/troubleshooting/oauth-callbacks) and [Token refresh](/troubleshooting/token-refresh). @@ -155,7 +153,7 @@ For provider-specific errors, see [OAuth callbacks](/troubleshooting/oauth-callb The proxy injection model the skill uses under the hood. - Drop below the skill into `AuthService` for fine-grained control. + Use `authsome export` or the daemon HTTP API when the proxy is not enough. Every service Hermes can log you into out of the box. diff --git a/docs/site/integrations/agents/index.mdx b/docs/site/integrations/agents/index.mdx index 9774541d..62f65a0b 100644 --- a/docs/site/integrations/agents/index.mdx +++ b/docs/site/integrations/agents/index.mdx @@ -9,7 +9,7 @@ Authsome is provider-side, not framework-side. It manages credentials for the se The supported pattern for every framework is the same: **wrap the agent invocation with `authsome run --`**. The local HTTP proxy intercepts outbound requests and injects the right `Authorization` header per provider. The agent's environment never contains real secrets. -If your agent is Python-native and you're embedding authsome inside a larger orchestrator with custom storage or wiring, the library is available as a secondary surface. For everything else, the CLI and proxy are the right tools. +If the proxy cannot intercept your SDK's traffic, use `authsome export` or the daemon HTTP API. See [Python library](/reference/python-library). This section has a page per agent framework with the install path, the proxy wiring, and any framework-specific notes. @@ -29,7 +29,7 @@ This section has a page per agent framework with the install path, the proxy wir OpenCode CLI. Use the proxy or env-var export. - Multi-agent runtime. Per-agent profiles isolate credentials. + Multi-agent runtime. Separate `AUTHSOME_HOME` directories isolate credentials. Nous Research's self-improving agent. Installs the authsome skill via agentskills.io. @@ -71,18 +71,9 @@ python my_agent.py Same vault, same refresh, but the key is in the agent's environment. -### Embedding the library +### Export or daemon API -If you're building a larger Python orchestrator around authsome, you can drop below the CLI: - -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("github", connection="default") -``` - -This is the embedding case. For everything else, the proxy is simpler. See [Python library](/reference/python-library). +If the proxy cannot intercept your SDK's traffic, use `authsome export` or the daemon HTTP API. See [Python library](/reference/python-library). ## Per-framework notes diff --git a/docs/site/integrations/agents/langchain.mdx b/docs/site/integrations/agents/langchain.mdx index b66a63ea..5359388c 100644 --- a/docs/site/integrations/agents/langchain.mdx +++ b/docs/site/integrations/agents/langchain.mdx @@ -31,38 +31,26 @@ search = SerpAPIWrapper() For tools that authsome doesn't bundle, add a [custom provider](/guides/custom-providers) so the proxy can match by host. -## Embedding the library +## Export when the proxy is not enough -If you're building a larger orchestrator around LangChain and need to pass tokens explicitly (different connection per call, or TLS-pinned SDKs that bypass the proxy), drop down to the library: +If you're building a larger orchestrator around LangChain and need to pass tokens explicitly (different connection per call, or TLS-pinned SDKs that bypass the proxy), export credentials first: -```python -from authsome.server.dependencies import create_auth_service -from langchain_openai import ChatOpenAI -from langchain_community.tools.github.tool import GitHubAction - -auth = create_auth_service() - -llm = ChatOpenAI( - api_key=auth.get_access_token("openai"), - model="gpt-4o-mini", -) - -github = GitHubAction( - github_access_token=auth.get_access_token("github"), -) +```bash +eval "$(authsome export openai --format env)" +eval "$(authsome export github --format env)" ``` -Refresh is transparent. Construct the clients once per request rather than caching them across long-running processes if your tokens have short TTLs. +Then construct LangChain clients as usual — they read the exported env vars. ## Async clients -`AsyncChatOpenAI` and other async wrappers work identically. Authsome's auth layer is synchronous; if you do use the library, call `get_access_token` once at client construction and pass the value in. +`AsyncChatOpenAI` and other async wrappers work identically under `authsome run`. ## Multi-account workflows -```python -work = auth.get_access_token("github", connection="work") -personal = auth.get_access_token("github", connection="personal") +```bash +eval "$(authsome export github --connection work --format env)" +eval "$(authsome export github --connection personal --format env)" ``` See [Multiple connections per provider](/guides/multiple-connections). diff --git a/docs/site/integrations/agents/llamaindex.mdx b/docs/site/integrations/agents/llamaindex.mdx index 3e84cbf5..f9fd7001 100644 --- a/docs/site/integrations/agents/llamaindex.mdx +++ b/docs/site/integrations/agents/llamaindex.mdx @@ -28,42 +28,21 @@ LlamaIndex's data readers cover dozens of services (Notion, Confluence, Slack, G For services not bundled, see [Custom providers](/guides/custom-providers). -## Embedding the library +## Export when the proxy is not enough -If you're building a larger orchestrator around LlamaIndex and need explicit per-call control: - -```python -from authsome.server.dependencies import create_auth_service -from llama_index.core import Settings -from llama_index.llms.openai import OpenAI -from llama_index.readers.github import GithubRepositoryReader, GithubClient - -auth = create_auth_service() - -Settings.llm = OpenAI(api_key=auth.get_access_token("openai")) - -reader = GithubRepositoryReader( - github_client=GithubClient(auth.get_access_token("github")), - owner="agentrhq", - repo="authsome", -) -docs = reader.load_data(branch="main") +```bash +eval "$(authsome export openai --format env)" +eval "$(authsome export github --format env)" +python my_index.py ``` -Refresh is silent. Re-call `get_access_token` if your process lives long enough to outlast a token's TTL. +LlamaIndex clients read the exported env vars as usual. ## Multi-account -```python -docs_personal = reader_personal.load_data() -docs_work = reader_work.load_data() -``` - -with: - -```python -auth.get_access_token("github", connection="personal") -auth.get_access_token("github", connection="work") +```bash +eval "$(authsome export github --connection personal --format env)" +eval "$(authsome export github --connection work --format env)" ``` See [Multiple connections per provider](/guides/multiple-connections). @@ -72,7 +51,7 @@ See [Multiple connections per provider](/guides/multiple-connections). - `AuthService` and the auth-layer API. + the CLI export path or the daemon HTTP API. Add a data-source provider authsome doesn't ship. diff --git a/docs/site/integrations/agents/nanoclaw.mdx b/docs/site/integrations/agents/nanoclaw.mdx index d7620b7c..98c4c2cb 100644 --- a/docs/site/integrations/agents/nanoclaw.mdx +++ b/docs/site/integrations/agents/nanoclaw.mdx @@ -20,32 +20,24 @@ authsome run -- python -m The runner sees placeholder env vars. Outbound HTTPS to matched providers is authenticated at the proxy layer. This is the recommended path. -## Embedding the library +## Export when the proxy is not enough -If you're wiring authsome into a larger orchestrator and want explicit per-call control, call the library directly from your agent code: +If you need explicit env vars in the runner process: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() - -github_token = auth.get_access_token("github") -openai_key = auth.get_access_token("openai") - -# Pass to your runner's agent constructor however it expects credentials -# (env vars, kwargs, config object: runner-specific). +```bash +eval "$(authsome export github --format env)" +eval "$(authsome export openai --format env)" +python -m ``` -Refresh is silent. The agent never holds an expired token long enough to matter. - -See [Python library](/reference/python-library) for the full surface. +See [Python library](/reference/python-library) for the daemon HTTP API. ## When to use which -| Use the proxy | Use the library | -|----------------|------------------| -| You want a single layer that catches every outbound call. | You want fine-grained control over which connection to use per agent. | -| You're using third-party clients you can't easily modify. | The agent is yours and you can pass tokens directly. | +| Use the proxy | Use export | +|----------------|------------| +| You want a single layer that catches every outbound call. | You need fine-grained control over which connection to use per agent. | +| You're using third-party clients you can't easily modify. | The agent is yours and reads env vars directly. | | You need transparent injection for shell tools the agent spawns. | You don't spawn shell tools. | ## What's next @@ -55,6 +47,6 @@ See [Python library](/reference/python-library) for the full surface. The proxy injection model. - `AuthService` and the auth-layer API. + the CLI export path or the daemon HTTP API. diff --git a/docs/site/integrations/agents/openai-agents-sdk.mdx b/docs/site/integrations/agents/openai-agents-sdk.mdx index c04beb4c..c1891863 100644 --- a/docs/site/integrations/agents/openai-agents-sdk.mdx +++ b/docs/site/integrations/agents/openai-agents-sdk.mdx @@ -17,23 +17,13 @@ authsome run -- python my_agent.py The Agents SDK initializes with `OPENAI_API_KEY=authsome-proxy-managed`. Outbound requests to `api.openai.com` are intercepted and authenticated at the proxy layer. The agent's process never sees the real key. -## Alternative: pass the key explicitly +## Alternative: export into the environment -```python -from authsome.server.dependencies import create_auth_service -from openai import AsyncOpenAI -from agents import Agent, Runner, set_default_openai_client - -auth = create_auth_service() -client = AsyncOpenAI(api_key=auth.get_access_token("openai")) -set_default_openai_client(client) - -agent = Agent(name="my-agent", instructions="...") -result = await Runner.run(agent, "do the thing") +```bash +eval "$(authsome export openai --format env)" +python my_agent.py ``` -Use this when you need to control which connection the SDK uses, or when the proxy isn't an option. - ## Multi-account workflows ```bash @@ -41,11 +31,8 @@ authsome login openai --connection personal authsome login openai --connection team ``` -Through the proxy, set the default with `--force`. In code, pass `connection=`: - -```python -key = auth.get_access_token("openai", connection="team") -client = AsyncOpenAI(api_key=key) +```bash +eval "$(authsome export openai --connection team --format env)" ``` ## Tools that hit other providers diff --git a/docs/site/integrations/agents/opencode.mdx b/docs/site/integrations/agents/opencode.mdx index 0786524c..ae96fedd 100644 --- a/docs/site/integrations/agents/opencode.mdx +++ b/docs/site/integrations/agents/opencode.mdx @@ -26,11 +26,9 @@ OpenCode sees placeholder env vars (`OPENAI_API_KEY=authsome-proxy-managed`) but If you're orchestrating OpenCode from a larger Python program and need explicit per-call control, drop below the proxy: -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("openai", connection="default") +```bash +authsome run -- python my_agent.py +# or: eval "$(authsome export --format env)" ``` See [Python library](/reference/python-library). diff --git a/docs/site/integrations/agents/python.mdx b/docs/site/integrations/agents/python.mdx index 7e26cb6c..5a97c9b2 100644 --- a/docs/site/integrations/agents/python.mdx +++ b/docs/site/integrations/agents/python.mdx @@ -38,30 +38,21 @@ print(r.json()) No authsome import in the script. The proxy does the work. This is the recommended path for almost every script. -## Embedding the library +## Export when the proxy is not enough -When you're wiring authsome into a larger Python orchestrator and want per-call connection selection or programmatic access to connection metadata: +When you need to pass tokens explicitly (TLS-pinned SDKs, non-HTTP protocols, or per-call connection selection): -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() - -openai_key = auth.get_access_token("openai", connection="default") -github_token = auth.get_access_token("github", connection="work") - -import httpx -r = httpx.get( - "https://api.openai.com/v1/models", - headers={"Authorization": f"Bearer {openai_key}"}, -) +```bash +eval "$(authsome export openai --format env)" +eval "$(authsome export github --connection work --format env)" +python my_script.py ``` -Refresh is silent. Re-call `get_access_token` if your process outlives a token TTL. See [Python library](/reference/python-library) for the full surface. +See [Python library](/reference/python-library) for the daemon HTTP API when building custom orchestration. ## When the proxy isn't enough -The library is the right tool when: +The export path is the right tool when: - The SDK pins TLS certificates and refuses to trust the mitmproxy CA. - You're using non-HTTP protocols (WebSockets, gRPC over HTTP/2, raw TCP) that the proxy can't intercept. @@ -72,9 +63,9 @@ Otherwise, the proxy is simpler. ## Multi-account -```python -auth.get_access_token("github", connection="personal") -auth.get_access_token("github", connection="work") +```bash +authsome export github --connection personal --format env +authsome export github --connection work --format env ``` See [Multiple connections per provider](/guides/multiple-connections). diff --git a/docs/site/integrations/api-key/ahrefs.mdx b/docs/site/integrations/api-key/ahrefs.mdx index 6fd683d6..fa610292 100644 --- a/docs/site/integrations/api-key/ahrefs.mdx +++ b/docs/site/integrations/api-key/ahrefs.mdx @@ -46,7 +46,7 @@ authsome get ahrefs --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export ahrefs --format env)" echo $AHREFS_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("ahrefs", connection="default") -``` - Under the proxy, authsome sets `AHREFS_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.ahrefs.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect ahrefs > ~/.authsome/providers/ahrefs.json authsome list # source now shows "custom" for ahrefs ``` - ## What's next diff --git a/docs/site/integrations/api-key/apollo.mdx b/docs/site/integrations/api-key/apollo.mdx index 8b955ac2..638673f9 100644 --- a/docs/site/integrations/api-key/apollo.mdx +++ b/docs/site/integrations/api-key/apollo.mdx @@ -46,7 +46,7 @@ authsome get apollo --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export apollo --format env)" echo $APOLLO_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("apollo", connection="default") -``` - Under the proxy, authsome sets `APOLLO_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.apollo.io`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect apollo > ~/.authsome/providers/apollo.json authsome list # source now shows "custom" for apollo ``` - ## What's next diff --git a/docs/site/integrations/api-key/ashby.mdx b/docs/site/integrations/api-key/ashby.mdx index 9b8f38cb..1e2b2b9f 100644 --- a/docs/site/integrations/api-key/ashby.mdx +++ b/docs/site/integrations/api-key/ashby.mdx @@ -46,7 +46,7 @@ authsome get ashby --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export ashby --format env)" echo $ASHBY_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("ashby", connection="default") -``` - Under the proxy, authsome sets `ASHBY_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.ashbyhq.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect ashby > ~/.authsome/providers/ashby.json authsome list # source now shows "custom" for ashby ``` - ## What's next diff --git a/docs/site/integrations/api-key/beehiiv.mdx b/docs/site/integrations/api-key/beehiiv.mdx index a7dff983..1ff083fc 100644 --- a/docs/site/integrations/api-key/beehiiv.mdx +++ b/docs/site/integrations/api-key/beehiiv.mdx @@ -46,7 +46,7 @@ authsome get beehiiv --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export beehiiv --format env)" echo $BEEHIIV_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("beehiiv", connection="default") -``` - Under the proxy, authsome sets `BEEHIIV_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.beehiiv.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect beehiiv > ~/.authsome/providers/beehiiv.json authsome list # source now shows "custom" for beehiiv ``` - ## What's next diff --git a/docs/site/integrations/api-key/brevo.mdx b/docs/site/integrations/api-key/brevo.mdx index ca5f208b..6f1f37ed 100644 --- a/docs/site/integrations/api-key/brevo.mdx +++ b/docs/site/integrations/api-key/brevo.mdx @@ -46,7 +46,7 @@ authsome get brevo --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export brevo --format env)" echo $BREVO_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("brevo", connection="default") -``` - Under the proxy, authsome sets `BREVO_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.brevo.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect brevo > ~/.authsome/providers/brevo.json authsome list # source now shows "custom" for brevo ``` - ## What's next diff --git a/docs/site/integrations/api-key/buffer.mdx b/docs/site/integrations/api-key/buffer.mdx index dd88ad9b..cdfde637 100644 --- a/docs/site/integrations/api-key/buffer.mdx +++ b/docs/site/integrations/api-key/buffer.mdx @@ -47,7 +47,7 @@ authsome get buffer --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -60,13 +60,6 @@ eval "$(authsome export buffer --format env)" echo $BUFFER_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("buffer", connection="default") -``` - Under the proxy, authsome sets `BUFFER_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.bufferapp.com`. The child process never sees the actual value. @@ -98,7 +91,6 @@ authsome inspect buffer > ~/.authsome/providers/buffer.json authsome list # source now shows "custom" for buffer ``` - ## What's next diff --git a/docs/site/integrations/api-key/calendly.mdx b/docs/site/integrations/api-key/calendly.mdx index 209800ce..37e61df8 100644 --- a/docs/site/integrations/api-key/calendly.mdx +++ b/docs/site/integrations/api-key/calendly.mdx @@ -46,7 +46,7 @@ authsome get calendly --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export calendly --format env)" echo $CALENDLY_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("calendly", connection="default") -``` - Under the proxy, authsome sets `CALENDLY_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.calendly.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect calendly > ~/.authsome/providers/calendly.json authsome list # source now shows "custom" for calendly ``` - ## What's next diff --git a/docs/site/integrations/api-key/clearbit.mdx b/docs/site/integrations/api-key/clearbit.mdx index 9ec2d675..00310e8b 100644 --- a/docs/site/integrations/api-key/clearbit.mdx +++ b/docs/site/integrations/api-key/clearbit.mdx @@ -48,7 +48,7 @@ authsome get clearbit --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -61,13 +61,6 @@ eval "$(authsome export clearbit --format env)" echo $CLEARBIT_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("clearbit", connection="default") -``` - Under the proxy, authsome sets `CLEARBIT_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.clearbit.com`. The child process never sees the actual value. @@ -99,7 +92,6 @@ authsome inspect clearbit > ~/.authsome/providers/clearbit.json authsome list # source now shows "custom" for clearbit ``` - ## What's next diff --git a/docs/site/integrations/api-key/dub.mdx b/docs/site/integrations/api-key/dub.mdx index 3911c102..95ad1706 100644 --- a/docs/site/integrations/api-key/dub.mdx +++ b/docs/site/integrations/api-key/dub.mdx @@ -46,7 +46,7 @@ authsome get dub --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export dub --format env)" echo $DUB_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("dub", connection="default") -``` - Under the proxy, authsome sets `DUB_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.dub.co`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect dub > ~/.authsome/providers/dub.json authsome list # source now shows "custom" for dub ``` - ## What's next diff --git a/docs/site/integrations/api-key/g2.mdx b/docs/site/integrations/api-key/g2.mdx index a113e28e..38c4a6b9 100644 --- a/docs/site/integrations/api-key/g2.mdx +++ b/docs/site/integrations/api-key/g2.mdx @@ -48,7 +48,7 @@ authsome get g2 --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -61,13 +61,6 @@ eval "$(authsome export g2 --format env)" echo $G2_API_TOKEN ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("g2", connection="default") -``` - Under the proxy, authsome sets `G2_API_TOKEN=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.g2.com`. The child process never sees the actual value. @@ -99,7 +92,6 @@ authsome inspect g2 > ~/.authsome/providers/g2.json authsome list # source now shows "custom" for g2 ``` - ## What's next diff --git a/docs/site/integrations/api-key/hunter.mdx b/docs/site/integrations/api-key/hunter.mdx index ce0c6841..2d8dd97e 100644 --- a/docs/site/integrations/api-key/hunter.mdx +++ b/docs/site/integrations/api-key/hunter.mdx @@ -46,7 +46,7 @@ authsome get hunter --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export hunter --format env)" echo $HUNTER_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("hunter", connection="default") -``` - Under the proxy, authsome sets `HUNTER_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.hunter.io`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect hunter > ~/.authsome/providers/hunter.json authsome list # source now shows "custom" for hunter ``` - ## What's next diff --git a/docs/site/integrations/api-key/index.mdx b/docs/site/integrations/api-key/index.mdx index 7b5d5bdf..a3c8f962 100644 --- a/docs/site/integrations/api-key/index.mdx +++ b/docs/site/integrations/api-key/index.mdx @@ -66,7 +66,7 @@ There is no OAuth dance. The flow is: Some providers ship a regex (`key_pattern`). If your input doesn't match, authsome rejects it with a hint. - The key is encrypted under the active profile and written to the vault. + The key is encrypted in the active vault and written to the vault. @@ -92,14 +92,7 @@ eval "$(authsome export openai --format env)" ### From Python -```python -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("openai", connection="default") -``` - -The function `get_access_token` is shared with the OAuth path. For API-key providers it returns the stored key. +Run under the proxy (recommended) or export into the environment before launching your script. See [Python library](/reference/python-library). ## Add an API-key provider @@ -109,7 +102,6 @@ For a service authsome doesn't bundle (Anthropic, Stripe, Twilio, and many other 2. Write a JSON definition. See [Custom providers](/guides/custom-providers) for the template. 3. `authsome register ./.json`. - ## What's next diff --git a/docs/site/integrations/api-key/instantly.mdx b/docs/site/integrations/api-key/instantly.mdx index c22d075d..2524f6f7 100644 --- a/docs/site/integrations/api-key/instantly.mdx +++ b/docs/site/integrations/api-key/instantly.mdx @@ -46,7 +46,7 @@ authsome get instantly --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export instantly --format env)" echo $INSTANTLY_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("instantly", connection="default") -``` - Under the proxy, authsome sets `INSTANTLY_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.instantly.ai`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect instantly > ~/.authsome/providers/instantly.json authsome list # source now shows "custom" for instantly ``` - ## What's next diff --git a/docs/site/integrations/api-key/intercom.mdx b/docs/site/integrations/api-key/intercom.mdx index aafe8da2..2bc23764 100644 --- a/docs/site/integrations/api-key/intercom.mdx +++ b/docs/site/integrations/api-key/intercom.mdx @@ -49,7 +49,7 @@ authsome get intercom --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -62,13 +62,6 @@ eval "$(authsome export intercom --format env)" echo $INTERCOM_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("intercom", connection="default") -``` - Under the proxy, authsome sets `INTERCOM_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.intercom.io`. The child process never sees the actual value. @@ -100,7 +93,6 @@ authsome inspect intercom > ~/.authsome/providers/intercom.json authsome list # source now shows "custom" for intercom ``` - ## What's next diff --git a/docs/site/integrations/api-key/keywords-everywhere.mdx b/docs/site/integrations/api-key/keywords-everywhere.mdx index 1270fd92..0e69bcd3 100644 --- a/docs/site/integrations/api-key/keywords-everywhere.mdx +++ b/docs/site/integrations/api-key/keywords-everywhere.mdx @@ -46,7 +46,7 @@ authsome get keywords-everywhere --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export keywords-everywhere --format env)" echo $KEYWORDS_EVERYWHERE_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("keywords-everywhere", connection="default") -``` - Under the proxy, authsome sets `KEYWORDS_EVERYWHERE_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.keywordseverywhere.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect keywords-everywhere > ~/.authsome/providers/keywords-everywhere authsome list # source now shows "custom" for keywords-everywhere ``` - ## What's next diff --git a/docs/site/integrations/api-key/klaviyo.mdx b/docs/site/integrations/api-key/klaviyo.mdx index d82fa7fe..670dd15c 100644 --- a/docs/site/integrations/api-key/klaviyo.mdx +++ b/docs/site/integrations/api-key/klaviyo.mdx @@ -46,7 +46,7 @@ authsome get klaviyo --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export klaviyo --format env)" echo $KLAVIYO_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("klaviyo", connection="default") -``` - Under the proxy, authsome sets `KLAVIYO_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `a.klaviyo.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect klaviyo > ~/.authsome/providers/klaviyo.json authsome list # source now shows "custom" for klaviyo ``` - ## What's next diff --git a/docs/site/integrations/api-key/lemlist.mdx b/docs/site/integrations/api-key/lemlist.mdx index c1a93a14..4da6e502 100644 --- a/docs/site/integrations/api-key/lemlist.mdx +++ b/docs/site/integrations/api-key/lemlist.mdx @@ -46,7 +46,7 @@ authsome get lemlist --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export lemlist --format env)" echo $LEMLIST_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("lemlist", connection="default") -``` - Under the proxy, authsome sets `LEMLIST_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.lemlist.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect lemlist > ~/.authsome/providers/lemlist.json authsome list # source now shows "custom" for lemlist ``` - ## What's next diff --git a/docs/site/integrations/api-key/livestorm.mdx b/docs/site/integrations/api-key/livestorm.mdx index 38e97605..d4030ed8 100644 --- a/docs/site/integrations/api-key/livestorm.mdx +++ b/docs/site/integrations/api-key/livestorm.mdx @@ -46,7 +46,7 @@ authsome get livestorm --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export livestorm --format env)" echo $LIVESTORM_API_TOKEN ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("livestorm", connection="default") -``` - Under the proxy, authsome sets `LIVESTORM_API_TOKEN=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.livestorm.co`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect livestorm > ~/.authsome/providers/livestorm.json authsome list # source now shows "custom" for livestorm ``` - ## What's next diff --git a/docs/site/integrations/api-key/mailchimp.mdx b/docs/site/integrations/api-key/mailchimp.mdx index f70cc05f..13f70878 100644 --- a/docs/site/integrations/api-key/mailchimp.mdx +++ b/docs/site/integrations/api-key/mailchimp.mdx @@ -49,7 +49,7 @@ authsome get mailchimp --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -62,13 +62,6 @@ eval "$(authsome export mailchimp --format env)" echo $MAILCHIMP_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("mailchimp", connection="default") -``` - Under the proxy, authsome sets `MAILCHIMP_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.mailchimp.com`. The child process never sees the actual value. @@ -100,7 +93,6 @@ authsome inspect mailchimp > ~/.authsome/providers/mailchimp.json authsome list # source now shows "custom" for mailchimp ``` - ## What's next diff --git a/docs/site/integrations/api-key/mention-me.mdx b/docs/site/integrations/api-key/mention-me.mdx index 674c79ee..cd66e83b 100644 --- a/docs/site/integrations/api-key/mention-me.mdx +++ b/docs/site/integrations/api-key/mention-me.mdx @@ -48,7 +48,7 @@ authsome get mention-me --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -61,13 +61,6 @@ eval "$(authsome export mention-me --format env)" echo $MENTIONME_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("mention-me", connection="default") -``` - Under the proxy, authsome sets `MENTIONME_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `mention-me.com`. The child process never sees the actual value. @@ -99,7 +92,6 @@ authsome inspect mention-me > ~/.authsome/providers/mention-me.json authsome list # source now shows "custom" for mention-me ``` - ## What's next diff --git a/docs/site/integrations/api-key/openai.mdx b/docs/site/integrations/api-key/openai.mdx index 01fc88cc..7d24e7ba 100644 --- a/docs/site/integrations/api-key/openai.mdx +++ b/docs/site/integrations/api-key/openai.mdx @@ -56,7 +56,7 @@ authsome get openai --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -69,21 +69,6 @@ eval "$(authsome export openai --format env)" echo $OPENAI_API_KEY # sk-... ``` -```python Python library -from authsome.server.dependencies import create_auth_service -from openai import OpenAI - -auth = create_auth_service() -key = auth.get_access_token("openai", connection="default") - -client = OpenAI(api_key=key) -resp = client.chat.completions.create( - model="gpt-4o-mini", - messages=[{"role": "user", "content": "ping"}], -) -print(resp.choices[0].message.content) -``` - Under the proxy, authsome sets `OPENAI_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.openai.com`. The child process never sees the actual value. With the OpenAI Python SDK, no code change is required: it reads the env var, makes the request, and the proxy substitutes the header on the way out. diff --git a/docs/site/integrations/api-key/optimizely.mdx b/docs/site/integrations/api-key/optimizely.mdx index 36f283ae..5fceeec7 100644 --- a/docs/site/integrations/api-key/optimizely.mdx +++ b/docs/site/integrations/api-key/optimizely.mdx @@ -46,7 +46,7 @@ authsome get optimizely --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export optimizely --format env)" echo $OPTIMIZELY_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("optimizely", connection="default") -``` - Under the proxy, authsome sets `OPTIMIZELY_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.optimizely.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect optimizely > ~/.authsome/providers/optimizely.json authsome list # source now shows "custom" for optimizely ``` - ## What's next diff --git a/docs/site/integrations/api-key/postmark.mdx b/docs/site/integrations/api-key/postmark.mdx index 98657520..ebd9a4b0 100644 --- a/docs/site/integrations/api-key/postmark.mdx +++ b/docs/site/integrations/api-key/postmark.mdx @@ -46,7 +46,7 @@ authsome get postmark --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export postmark --format env)" echo $POSTMARK_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("postmark", connection="default") -``` - Under the proxy, authsome sets `POSTMARK_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.postmarkapp.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect postmark > ~/.authsome/providers/postmark.json authsome list # source now shows "custom" for postmark ``` - ## What's next diff --git a/docs/site/integrations/api-key/resend.mdx b/docs/site/integrations/api-key/resend.mdx index 6f0cd462..39b8f0fb 100644 --- a/docs/site/integrations/api-key/resend.mdx +++ b/docs/site/integrations/api-key/resend.mdx @@ -46,7 +46,7 @@ authsome get resend --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export resend --format env)" echo $RESEND_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("resend", connection="default") -``` - Under the proxy, authsome sets `RESEND_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.resend.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect resend > ~/.authsome/providers/resend.json authsome list # source now shows "custom" for resend ``` - ## What's next diff --git a/docs/site/integrations/api-key/rewardful.mdx b/docs/site/integrations/api-key/rewardful.mdx index ca9ec4a4..40f2ad27 100644 --- a/docs/site/integrations/api-key/rewardful.mdx +++ b/docs/site/integrations/api-key/rewardful.mdx @@ -46,7 +46,7 @@ authsome get rewardful --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export rewardful --format env)" echo $REWARDFUL_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("rewardful", connection="default") -``` - Under the proxy, authsome sets `REWARDFUL_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.getrewardful.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect rewardful > ~/.authsome/providers/rewardful.json authsome list # source now shows "custom" for rewardful ``` - ## What's next diff --git a/docs/site/integrations/api-key/savvycal.mdx b/docs/site/integrations/api-key/savvycal.mdx index 41300c81..77c32004 100644 --- a/docs/site/integrations/api-key/savvycal.mdx +++ b/docs/site/integrations/api-key/savvycal.mdx @@ -46,7 +46,7 @@ authsome get savvycal --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export savvycal --format env)" echo $SAVVYCAL_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("savvycal", connection="default") -``` - Under the proxy, authsome sets `SAVVYCAL_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.savvycal.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect savvycal > ~/.authsome/providers/savvycal.json authsome list # source now shows "custom" for savvycal ``` - ## What's next diff --git a/docs/site/integrations/api-key/semrush.mdx b/docs/site/integrations/api-key/semrush.mdx index 9910a9ce..0fae7ed9 100644 --- a/docs/site/integrations/api-key/semrush.mdx +++ b/docs/site/integrations/api-key/semrush.mdx @@ -46,7 +46,7 @@ authsome get semrush --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export semrush --format env)" echo $SEMRUSH_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("semrush", connection="default") -``` - Under the proxy, authsome sets `SEMRUSH_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.semrush.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect semrush > ~/.authsome/providers/semrush.json authsome list # source now shows "custom" for semrush ``` - ## What's next diff --git a/docs/site/integrations/api-key/sendgrid.mdx b/docs/site/integrations/api-key/sendgrid.mdx index 61ade9f2..c0267f58 100644 --- a/docs/site/integrations/api-key/sendgrid.mdx +++ b/docs/site/integrations/api-key/sendgrid.mdx @@ -47,7 +47,7 @@ authsome get sendgrid --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -60,13 +60,6 @@ eval "$(authsome export sendgrid --format env)" echo $SENDGRID_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("sendgrid", connection="default") -``` - Under the proxy, authsome sets `SENDGRID_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.sendgrid.com`. The child process never sees the actual value. @@ -98,7 +91,6 @@ authsome inspect sendgrid > ~/.authsome/providers/sendgrid.json authsome list # source now shows "custom" for sendgrid ``` - ## What's next diff --git a/docs/site/integrations/api-key/tolt.mdx b/docs/site/integrations/api-key/tolt.mdx index fbb708d0..a8945f30 100644 --- a/docs/site/integrations/api-key/tolt.mdx +++ b/docs/site/integrations/api-key/tolt.mdx @@ -46,7 +46,7 @@ authsome get tolt --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export tolt --format env)" echo $TOLT_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("tolt", connection="default") -``` - Under the proxy, authsome sets `TOLT_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.tolt.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect tolt > ~/.authsome/providers/tolt.json authsome list # source now shows "custom" for tolt ``` - ## What's next diff --git a/docs/site/integrations/api-key/typeform.mdx b/docs/site/integrations/api-key/typeform.mdx index b531f4b2..dcfedfb4 100644 --- a/docs/site/integrations/api-key/typeform.mdx +++ b/docs/site/integrations/api-key/typeform.mdx @@ -46,7 +46,7 @@ authsome get typeform --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export typeform --format env)" echo $TYPEFORM_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("typeform", connection="default") -``` - Under the proxy, authsome sets `TYPEFORM_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.typeform.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect typeform > ~/.authsome/providers/typeform.json authsome list # source now shows "custom" for typeform ``` - ## What's next diff --git a/docs/site/integrations/api-key/wistia.mdx b/docs/site/integrations/api-key/wistia.mdx index ba81cd2d..4d4184d5 100644 --- a/docs/site/integrations/api-key/wistia.mdx +++ b/docs/site/integrations/api-key/wistia.mdx @@ -48,7 +48,7 @@ authsome get wistia --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -61,13 +61,6 @@ eval "$(authsome export wistia --format env)" echo $WISTIA_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("wistia", connection="default") -``` - Under the proxy, authsome sets `WISTIA_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.wistia.com`. The child process never sees the actual value. @@ -99,7 +92,6 @@ authsome inspect wistia > ~/.authsome/providers/wistia.json authsome list # source now shows "custom" for wistia ``` - ## What's next diff --git a/docs/site/integrations/api-key/zapier.mdx b/docs/site/integrations/api-key/zapier.mdx index f904e580..2a39d09e 100644 --- a/docs/site/integrations/api-key/zapier.mdx +++ b/docs/site/integrations/api-key/zapier.mdx @@ -46,7 +46,7 @@ authsome get zapier --field status ## Use the key -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -59,13 +59,6 @@ eval "$(authsome export zapier --format env)" echo $ZAPIER_API_KEY ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -key = auth.get_access_token("zapier", connection="default") -``` - Under the proxy, authsome sets `ZAPIER_API_KEY=authsome-proxy-managed` in the child's environment and injects the real key into outbound requests to `api.zapier.com`. The child process never sees the actual value. @@ -97,7 +90,6 @@ authsome inspect zapier > ~/.authsome/providers/zapier.json authsome list # source now shows "custom" for zapier ``` - ## What's next diff --git a/docs/site/integrations/oauth/atlassian.mdx b/docs/site/integrations/oauth/atlassian.mdx index d68dafcb..e32c92bf 100644 --- a/docs/site/integrations/oauth/atlassian.mdx +++ b/docs/site/integrations/oauth/atlassian.mdx @@ -47,7 +47,7 @@ Dashboard: [https://developer.atlassian.com/console/myapps/](https://developer.a authsome login atlassian ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://auth.atlassian.com/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://auth.atlassian.com/authorize` for the authorization step. Verify: @@ -77,7 +77,7 @@ authsome login atlassian --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -89,13 +89,6 @@ authsome run -- python my_agent.py eval "$(authsome export atlassian --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("atlassian", connection="default") -``` - Under the proxy, authsome sets `ATLASSIAN_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.atlassian.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/discord.mdx b/docs/site/integrations/oauth/discord.mdx index 3e4e9b4a..fa5bf10a 100644 --- a/docs/site/integrations/oauth/discord.mdx +++ b/docs/site/integrations/oauth/discord.mdx @@ -51,7 +51,7 @@ Dashboard: [https://discord.com/developers/applications](https://discord.com/dev authsome login discord ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://discord.com/oauth2/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://discord.com/oauth2/authorize` for the authorization step. Verify: @@ -81,7 +81,7 @@ authsome login discord --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -93,13 +93,6 @@ authsome run -- python my_agent.py eval "$(authsome export discord --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("discord", connection="default") -``` - Under the proxy, authsome sets `DISCORD_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `discord.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/github.mdx b/docs/site/integrations/oauth/github.mdx index 03f2e7c9..0f91a4f7 100644 --- a/docs/site/integrations/oauth/github.mdx +++ b/docs/site/integrations/oauth/github.mdx @@ -84,7 +84,7 @@ What happens: - Authsome opens a local form at `http://127.0.0.1:7998`. Paste the `client_id` and `client_secret`. They are encrypted and stored under your profile, then reused on every subsequent login. + Authsome opens a local form at `http://127.0.0.1:7998`. Paste the `client_id` and `client_secret`. They are encrypted and stored in your vault, then reused on every subsequent login. A second browser window opens to `https://github.com/login/oauth/authorize`. Approve the requested scopes. @@ -158,7 +158,7 @@ authsome export github --connection personal --format env ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -171,20 +171,6 @@ eval "$(authsome export github --format env)" echo $GITHUB_ACCESS_TOKEN ``` -```python Python library -from authsome.server.dependencies import create_auth_service -import httpx - -auth = create_auth_service() -token = auth.get_access_token("github", connection="default") - -r = httpx.get( - "https://api.github.com/user", - headers={"Authorization": f"Bearer {token}"}, -) -print(r.json()) -``` - Under the proxy, authsome sets `GITHUB_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.github.com`. The child process never sees the actual value. Refresh tokens are never exported. @@ -199,8 +185,6 @@ authsome inspect github > ~/.authsome/providers/github.json authsome list # source now shows "custom" for github ``` - - ## Troubleshooting | Symptom | Likely cause | Fix | diff --git a/docs/site/integrations/oauth/gitlab.mdx b/docs/site/integrations/oauth/gitlab.mdx index 0170e48b..ca2ac18c 100644 --- a/docs/site/integrations/oauth/gitlab.mdx +++ b/docs/site/integrations/oauth/gitlab.mdx @@ -47,7 +47,7 @@ Dashboard: [https://gitlab.com/-/user_settings/applications](https://gitlab.com/ authsome login gitlab ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://gitlab.com/oauth/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://gitlab.com/oauth/authorize` for the authorization step. Verify: @@ -87,7 +87,7 @@ authsome login gitlab --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -99,13 +99,6 @@ authsome run -- python my_agent.py eval "$(authsome export gitlab --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("gitlab", connection="default") -``` - Under the proxy, authsome sets `GITLAB_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `gitlab.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/google.mdx b/docs/site/integrations/oauth/google.mdx index d2cbc0b8..a7d26a8a 100644 --- a/docs/site/integrations/oauth/google.mdx +++ b/docs/site/integrations/oauth/google.mdx @@ -47,7 +47,7 @@ Dashboard: [https://console.cloud.google.com/apis/credentials](https://console.c authsome login google ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://accounts.google.com/o/oauth2/v2/auth` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://accounts.google.com/o/oauth2/v2/auth` for the authorization step. Verify: @@ -87,7 +87,7 @@ authsome login google --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -99,13 +99,6 @@ authsome run -- python my_agent.py eval "$(authsome export google --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("google", connection="default") -``` - Under the proxy, authsome sets `GOOGLE_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `regex:.*googleapis.*`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/hubspot.mdx b/docs/site/integrations/oauth/hubspot.mdx index b11477d4..0f452436 100644 --- a/docs/site/integrations/oauth/hubspot.mdx +++ b/docs/site/integrations/oauth/hubspot.mdx @@ -51,7 +51,7 @@ Dashboard: [https://app.hubspot.com/developer](https://app.hubspot.com/developer authsome login hubspot ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://app.hubspot.com/oauth/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://app.hubspot.com/oauth/authorize` for the authorization step. Verify: @@ -81,7 +81,7 @@ authsome login hubspot --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -93,13 +93,6 @@ authsome run -- python my_agent.py eval "$(authsome export hubspot --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("hubspot", connection="default") -``` - Under the proxy, authsome sets `HUBSPOT_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.hubapi.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/index.mdx b/docs/site/integrations/oauth/index.mdx index 08faa8a8..c379ee4c 100644 --- a/docs/site/integrations/oauth/index.mdx +++ b/docs/site/integrations/oauth/index.mdx @@ -57,8 +57,6 @@ If authsome doesn't bundle the provider you need: 2. Write a JSON definition. See [Custom providers](/guides/custom-providers) for templates. 3. `authsome register ./.json`. - - ## What's next diff --git a/docs/site/integrations/oauth/klaviyo-oauth.mdx b/docs/site/integrations/oauth/klaviyo-oauth.mdx index d58015e1..9ef90947 100644 --- a/docs/site/integrations/oauth/klaviyo-oauth.mdx +++ b/docs/site/integrations/oauth/klaviyo-oauth.mdx @@ -47,7 +47,7 @@ Dashboard: [https://www.klaviyo.com/oauth/client](https://www.klaviyo.com/oauth/ authsome login klaviyo-oauth ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://www.klaviyo.com/oauth/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://www.klaviyo.com/oauth/authorize` for the authorization step. Verify: @@ -77,7 +77,7 @@ authsome login klaviyo-oauth --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -89,13 +89,6 @@ authsome run -- python my_agent.py eval "$(authsome export klaviyo-oauth --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("klaviyo-oauth", connection="default") -``` - Under the proxy, authsome sets `KLAVIYO_OAUTH_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `a.klaviyo.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/linear.mdx b/docs/site/integrations/oauth/linear.mdx index 575c86ec..ba65b750 100644 --- a/docs/site/integrations/oauth/linear.mdx +++ b/docs/site/integrations/oauth/linear.mdx @@ -46,7 +46,7 @@ Dashboard: [https://linear.app/settings/api/applications/new](https://linear.app authsome login linear ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://linear.app/oauth/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://linear.app/oauth/authorize` for the authorization step. Verify: @@ -76,7 +76,7 @@ authsome login linear --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -88,13 +88,6 @@ authsome run -- python my_agent.py eval "$(authsome export linear --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("linear", connection="default") -``` - Under the proxy, authsome sets `LINEAR_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `regex:.*\.linear\.app`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/microsoft.mdx b/docs/site/integrations/oauth/microsoft.mdx index c255e2c0..33027f13 100644 --- a/docs/site/integrations/oauth/microsoft.mdx +++ b/docs/site/integrations/oauth/microsoft.mdx @@ -47,7 +47,7 @@ Dashboard: [https://entra.microsoft.com/](https://entra.microsoft.com/). authsome login microsoft ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://login.microsoftonline.com/common/oauth2/v2.0/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://login.microsoftonline.com/common/oauth2/v2.0/authorize` for the authorization step. Verify: @@ -87,7 +87,7 @@ authsome login microsoft --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -99,13 +99,6 @@ authsome run -- python my_agent.py eval "$(authsome export microsoft --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("microsoft", connection="default") -``` - Under the proxy, authsome sets `MICROSOFT_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `graph.microsoft.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/notion-dcr.mdx b/docs/site/integrations/oauth/notion-dcr.mdx index 50d66d82..70b166ba 100644 --- a/docs/site/integrations/oauth/notion-dcr.mdx +++ b/docs/site/integrations/oauth/notion-dcr.mdx @@ -37,7 +37,7 @@ Notion's MCP endpoint (`mcp.notion.com`) supports Dynamic Client Registration. Y authsome login notion_dcr ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://mcp.notion.com/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://mcp.notion.com/authorize` for the authorization step. Verify: @@ -57,7 +57,7 @@ authsome login notion_dcr --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -69,13 +69,6 @@ authsome run -- python my_agent.py eval "$(authsome export notion_dcr --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("notion_dcr", connection="default") -``` - Under the proxy, authsome sets `NOTION_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `mcp.notion.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/notion.mdx b/docs/site/integrations/oauth/notion.mdx index b15f0998..5726c7d0 100644 --- a/docs/site/integrations/oauth/notion.mdx +++ b/docs/site/integrations/oauth/notion.mdx @@ -51,7 +51,7 @@ Dashboard: [https://www.notion.so/my-integrations](https://www.notion.so/my-inte authsome login notion ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://api.notion.com/v1/oauth/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://api.notion.com/v1/oauth/authorize` for the authorization step. Verify: @@ -71,7 +71,7 @@ authsome login notion --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -83,13 +83,6 @@ authsome run -- python my_agent.py eval "$(authsome export notion --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("notion", connection="default") -``` - Under the proxy, authsome sets `NOTION_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.notion.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/postiz.mdx b/docs/site/integrations/oauth/postiz.mdx index 95d20d7a..91c66aa8 100644 --- a/docs/site/integrations/oauth/postiz.mdx +++ b/docs/site/integrations/oauth/postiz.mdx @@ -56,7 +56,7 @@ authsome login postiz --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -68,13 +68,6 @@ authsome run -- python my_agent.py eval "$(authsome export postiz --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("postiz", connection="default") -``` - Under the proxy, authsome sets `POSTIZ_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.postiz.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/slack.mdx b/docs/site/integrations/oauth/slack.mdx index 3b0e6fac..0b1ecaa2 100644 --- a/docs/site/integrations/oauth/slack.mdx +++ b/docs/site/integrations/oauth/slack.mdx @@ -51,7 +51,7 @@ Dashboard: [https://api.slack.com/apps](https://api.slack.com/apps). authsome login slack ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://slack.com/oauth/v2/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://slack.com/oauth/v2/authorize` for the authorization step. Verify: @@ -81,7 +81,7 @@ authsome login slack --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -93,13 +93,6 @@ authsome run -- python my_agent.py eval "$(authsome export slack --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("slack", connection="default") -``` - Under the proxy, authsome sets `SLACK_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `slack.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/integrations/oauth/x.mdx b/docs/site/integrations/oauth/x.mdx index 39f5399a..6abc684c 100644 --- a/docs/site/integrations/oauth/x.mdx +++ b/docs/site/integrations/oauth/x.mdx @@ -47,7 +47,7 @@ Dashboard: [https://developer.twitter.com/en/portal/dashboard](https://developer authsome login x ``` -The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted under your profile and reused on every subsequent login. A second browser window then opens to `https://twitter.com/i/oauth2/authorize` for the authorization step. +The first time, authsome opens a local form at `http://127.0.0.1:7998` to collect your `client_id` and `client_secret`. They are encrypted in your vault and reused on every subsequent login. A second browser window then opens to `https://twitter.com/i/oauth2/authorize` for the authorization step. Verify: @@ -77,7 +77,7 @@ authsome login x --connection work ## Use the token -Run the agent under the proxy. The library tab is for embedding authsome inside a larger Python orchestrator. +Run the agent under the proxy (recommended). @@ -89,13 +89,6 @@ authsome run -- python my_agent.py eval "$(authsome export x --format env)" ``` -```python Python library -from authsome.server.dependencies import create_auth_service - -auth = create_auth_service() -token = auth.get_access_token("x", connection="default") -``` - Under the proxy, authsome sets `X_ACCESS_TOKEN=authsome-proxy-managed` in the child's environment and injects the real token into outbound requests to `api.twitter.com`. The child process never sees the actual value. Refresh tokens are never exported. diff --git a/docs/site/quickstart.mdx b/docs/site/quickstart.mdx index 69579a30..c3b4f3d2 100644 --- a/docs/site/quickstart.mdx +++ b/docs/site/quickstart.mdx @@ -94,7 +94,7 @@ GitHub doesn't support Dynamic Client Registration, so before your first `authso -You'll paste both values into authsome's local browser bridge on the next step. They're stored encrypted under your profile and reused on every subsequent login. They are never accepted as command-line arguments. +You'll paste both values into authsome's local browser bridge on the next step. They're stored encrypted in your vault and reused on every subsequent login. They are never accepted as command-line arguments. ### Log in to a provider @@ -114,7 +114,7 @@ You'll paste both values into authsome's local browser bridge on the next step. - A second browser window opens to `https://github.com/login/oauth/authorize`. Click **Authorize** to grant the requested scopes (`repo` and `read:user` by default). GitHub exchanges the authorization for an OAuth access token, the callback lands on `http://127.0.0.1:7998/auth/callback/oauth`, and authsome stores the token encrypted under your profile. The terminal prints `Successfully logged in to github (default).` + A second browser window opens to `https://github.com/login/oauth/authorize`. Click **Authorize** to grant the requested scopes (`repo` and `read:user` by default). GitHub exchanges the authorization for an OAuth access token, the callback lands on `http://127.0.0.1:7998/auth/callback/oauth`, and authsome stores the token encrypted in your vault. The terminal prints `Successfully logged in to github (default).` The stored access token is what later commands inject. `client_id` and `client_secret` identify your OAuth app to GitHub; the access token is the user-level credential that makes API calls on your behalf. You don't need a separate PAT. @@ -161,7 +161,6 @@ A minimal agent that uses both credentials you just set up: it stars `agentrhq/a import os import urllib.request - def http(method: str, url: str, token: str, body: dict | None = None) -> dict | None: req = urllib.request.Request( url, @@ -175,7 +174,6 @@ A minimal agent that uses both credentials you just set up: it stars `agentrhq/a raw = r.read() return json.loads(raw) if raw else None - # 1. Star agentrhq/authsome with your GitHub OAuth token. http( "PUT", @@ -237,7 +235,7 @@ What happens: - Authsome POSTs to `https://mcp.notion.com/register` and Notion's OIDC server issues a fresh `client_id` and `client_secret`. They are stored encrypted under your profile. + Authsome POSTs to `https://mcp.notion.com/register` and Notion's OIDC server issues a fresh `client_id` and `client_secret`. They are stored encrypted in your vault. A browser window opens to `https://mcp.notion.com/authorize`. Click **Authorize** to grant access to your Notion workspace. The callback lands on `http://127.0.0.1:7998/auth/callback/oauth` and the terminal prints `Successfully logged in to notion_dcr (default).` diff --git a/docs/site/reference/daemon-api.mdx b/docs/site/reference/daemon-api.mdx index 7b07721a..bd65df3b 100644 --- a/docs/site/reference/daemon-api.mdx +++ b/docs/site/reference/daemon-api.mdx @@ -12,7 +12,7 @@ For the lifecycle, trust model, and `AUTHSOME_BASE_URL` / `AUTHSOME_BASE_URL` ov ## Health and readiness -### `GET /health` +### `GET /api/health` Liveness probe. Returns when the daemon process is up and responding, regardless of subsystem state. @@ -32,28 +32,40 @@ Liveness probe. Returns when the daemon process is up and responding, regardless Human-readable description of the effective master-key source. -### `GET /ready` +### `GET /api/ready` -Readiness probe. Verifies vault, schema version, and provider parsing. +Readiness probe. Verifies store, vault, identity, providers, and connections for the authenticated caller. - Overall readiness: `"ok"`, `"degraded"`, or `"unhealthy"`. + Overall readiness: `"ready"` when all checks pass, `"not_ready"` when `issues` is non-empty. Per-component status. - - `"ok"` if `~/.authsome/config.json` loaded and the schema version matches. Failures: `"missing"`, `"invalid_json"`, `"schema_version_mismatch"`. - - - `"ok"` if every stored record passes its Pydantic v2 model. Failures: `"version_mismatch"`, `"corrupt"`. + + `"ok"` if the relational store opens and passes a health probe. Failures: `"failed"`. - `"ok"` if the SQLite store for the active profile opens, the master key is reachable, and a no-op write succeeds. Failures: `"unreachable"`, `"locked"`, `"keyring_unavailable"`. + `"ok"` if the encrypted KV store accepts a read/write roundtrip. Failures: `"failed"`. + + + `"ok"` if the vault integrity check succeeds. Failures: `"failed"`. + + + `"ok"` if the caller's identity is registered. - `"ok"` if every bundled and user-registered provider JSON parses. Failures name the offending provider. + `"ok"` if every bundled and custom provider definition parses. Failures: `"failed"`. + + + `"ok"` if connection records load for the active vault. Failures: `"failed"`. + + + `"ok"` if the server config schema version matches. + + + Present when Redis is configured. `"ok"` after a successful ping. @@ -61,7 +73,7 @@ Readiness probe. Verifies vault, schema version, and provider parsing. Non-fatal observations that do not block readiness. Examples: a custom provider override of a bundled name, a master.key with mode 0644 instead of 0600. - Fatal problems. When non-empty, `status` is `"unhealthy"`. Each entry is a human-readable string suitable for surfacing in a monitoring alert. + Fatal problems. When non-empty, `status` is `"not_ready"`. Each entry is a human-readable string suitable for surfacing in a monitoring alert. The configured master-key resolution mode. @@ -73,24 +85,27 @@ Readiness probe. Verifies vault, schema version, and provider parsing. Human-readable description of the effective master-key source. -### `GET /whoami` +### `GET /api/whoami` -Returns the same payload as `authsome whoami`. +Returns context for the authenticated caller (same data as `authsome whoami --json`). Absolute path to the authsome home directory. - - The configured master-key resolution mode. + + Registered identity handle. - - The effective master-key source chosen at runtime. + + Opaque Principal identifier when the identity claim is accepted. - - Human-readable description of the effective master-key source. + + Opaque Vault identifier for the active credential store. - - Registered identity handle. + + `admin` or `user`. + + + The identity's `did:key` URI. ## Auth sessions @@ -99,36 +114,36 @@ These routes drive browser bridges and OAuth callbacks. The CLI starts a session | Method | Path | Purpose | |--------|------|---------| -| `POST` | `/auth/sessions` | Start a new auth session for a provider. | -| `GET` | `/auth/sessions/{session_id}` | Get session status. | -| `POST` | `/auth/sessions/{session_id}/resume` | Continue a paused or partial flow. | -| `GET` | `/auth/callback/oauth` | OAuth2 callback target (PKCE / DCR). | -| `GET` | `/auth/sessions/{session_id}/input` | Browser form for API-key or OAuth client credential entry. | -| `GET` | `/auth/sessions/{session_id}/device` | Device-code verification page. | -| `POST` | `/auth/sessions/{session_id}/input` | Submit values from the input form. | +| `POST` | `/api/auth/sessions` | Start a new auth session for a provider. | +| `GET` | `/api/auth/sessions/{session_id}` | Get session status. | +| `POST` | `/api/auth/sessions/{session_id}/resume` | Continue a paused or partial flow. | +| `GET` | `/auth/callback/oauth` | OAuth2 callback target (PKCE / DCR). Browser route, not under `/api`. | +| `GET` | `/api/auth/sessions/{session_id}/input` | Browser form for API-key or OAuth client credential entry. | +| `GET` | `/api/auth/sessions/{session_id}/device` | Device-code verification page. | +| `POST` | `/api/auth/sessions/{session_id}/input` | Submit values from the input form. | Session state is held in daemon memory. A daemon restart loses any session that is mid-flight. ## Connections -CRUD for connection records. Behind the scenes, every route goes through the AuthLayer, which manages decryption, refresh, and vault writes. +CRUD for connection records. Behind the scenes, every route goes through the daemon's credential service, which manages decryption, refresh, and vault writes. | Method | Path | Purpose | |--------|------|---------| -| `GET` | `/connections` | List every connection across all bundled and custom providers. | -| `GET` | `/connections/{provider}/{connection}` | Fetch one connection record. Secrets are redacted unless explicitly requested. | -| `POST` | `/connections/{provider}/{connection}/logout` | Remove a single connection record from the local store. | -| `POST` | `/connections/{provider}/revoke` | Call the provider's revocation endpoint (where supported) and clear all connections for the provider. | -| `POST` | `/connections/{provider}/{connection}/default` | Set this connection as the provider's default. | +| `GET` | `/api/connections` | List every connection across all bundled and custom providers. | +| `GET` | `/api/connections/{provider}/{connection}` | Fetch one connection record. Secrets are redacted unless explicitly requested. | +| `POST` | `/api/connections/{provider}/{connection}/logout` | Remove a single connection record from the local store. | +| `POST` | `/api/connections/{provider}/revoke` | Call the provider's revocation endpoint (where supported) and clear all connections for the provider. | +| `POST` | `/api/connections/{provider}/{connection}/default` | Set this connection as the provider's default. | ## Providers | Method | Path | Purpose | |--------|------|---------| -| `GET` | `/providers` | List every bundled and custom provider with auth type, flow, and source. | -| `GET` | `/providers/{provider}` | Full provider definition. | -| `POST` | `/providers` | Register a custom provider definition. | -| `DELETE` | `/providers/{provider}` | Remove a custom provider or reset a bundled one to its shipped form. | +| `GET` | `/api/providers` | List every bundled and custom provider with auth type, flow, and source. | +| `GET` | `/api/providers/{provider}` | Full provider definition. | +| `POST` | `/api/providers` | Register a custom provider definition. | +| `DELETE` | `/api/providers/{provider}` | Remove a custom provider or reset a bundled one to its shipped form. | ## Proxy resolution @@ -136,8 +151,8 @@ These routes back the local HTTP proxy started by `authsome run`. The proxy neve | Method | Path | Purpose | |--------|------|---------| -| `GET` | `/proxy/routes` | Return the provider-to-host routing table the proxy uses to decide which provider matches an outbound request. | -| `POST` | `/credentials/resolve` | Resolve a credential for a host. Returns the value the proxy injects into the `Authorization` header (or whatever header the provider's `api_key.header_name` declares). | +| `GET` | `/api/proxy/routes` | Return the provider-to-host routing table the proxy uses to decide which provider matches an outbound request. | +| `POST` | `/api/credentials/resolve` | Resolve a credential for a host. Returns the value the proxy injects into the `Authorization` header (or whatever header the provider's `api_key.header_name` declares). | ## Dashboard UI @@ -146,26 +161,32 @@ The Next.js dashboard is served as a static export at the daemon root. Browser-o | Method | Path | Purpose | |--------|------|---------| | `GET` | `/` | Static dashboard shell. | -| `POST` | `/session` | Return the dashboard URL for a PoP-authenticated local client. | -| `POST` | `/auth/login` | Create a browser dashboard session. | -| `POST` | `/auth/register` | Register an account and create a browser dashboard session. | -| `POST` | `/logout` | Clear the browser dashboard session. | -| `GET` | `/claim/{token}` | Render the account claim confirmation page. | -| `POST` | `/claim/{token}/confirm` | Attach a local identity to the signed-in account. | -| `POST` | `/auth/providers/{provider_name}/connect` | Start a provider login flow from the dashboard. | - +| `POST` | `/api/session` | Return the dashboard URL for a PoP-authenticated local client. | +| `POST` | `/api/auth/login` | Create a browser dashboard session. | +| `POST` | `/api/auth/register` | Register an account and create a browser dashboard session. | +| `POST` | `/api/logout` | Clear the browser dashboard session. | +| `GET` | `/api/claim/{token}` | Render the account claim confirmation page. | +| `POST` | `/api/claim/{token}/confirm` | Attach a local identity to the signed-in account. | +| `POST` | `/api/auth/providers/{provider_name}/connect` | Start a provider login flow from the dashboard. | ## Auth -There is **no** bearer token between the CLI, the proxy, and the daemon in v1. Loopback binding (`127.0.0.1`) is the only access control. See [Daemon trust boundary](/security/daemon-trust-boundary) for the trust model and known limitations. +Protected `/api/*` routes require a **Proof-of-Possession (PoP) JWT** in the `Authorization: PoP ` header, signed by the caller's Ed25519 identity key. The CLI and proxy attach this automatically. See [Daemon trust boundary](/security/daemon-trust-boundary) for the trust model. ## Calling the API directly +Unauthenticated liveness: + +```bash +curl -s http://127.0.0.1:7998/api/health +``` + +Protected routes require PoP signing (use the CLI or follow `src/authsome/cli/client.py`). Example paths: + ```bash -curl -s http://127.0.0.1:7998/health -curl -s http://127.0.0.1:7998/providers | jq '.[].name' -curl -s http://127.0.0.1:7998/connections | jq -curl -s http://127.0.0.1:7998/proxy/routes | jq +curl -s http://127.0.0.1:7998/api/providers | jq '.[].name' +curl -s http://127.0.0.1:7998/api/connections | jq +curl -s http://127.0.0.1:7998/api/proxy/routes | jq ``` When `AUTHSOME_BASE_URL` is set to a hosted daemon URL, replace `http://127.0.0.1:7998` with that URL. diff --git a/docs/site/reference/python-library.mdx b/docs/site/reference/python-library.mdx index 734eeffd..b5928a07 100644 --- a/docs/site/reference/python-library.mdx +++ b/docs/site/reference/python-library.mdx @@ -1,15 +1,19 @@ --- title: "Python library" sidebarTitle: "Python library" -description: "Use authsome from Python. AuthService is the public entry point; AuthLayer composes the building blocks." +description: "Use authsome from Python via the CLI, proxy, export, or daemon HTTP API." icon: "code" -keywords: ["authsome python", "AuthService", "authsome library", "auth.get_access_token", "authsome programmatic"] +keywords: ["authsome python", "authsome library", "authsome programmatic", "authsome daemon api"] --- -Authsome is a Python library as well as a CLI. The public surface lives in the top-level `authsome` package. +Authsome ships as a Python package, but the supported integration surface for agents is **not** an in-process credential API. Use one of these paths instead: + +1. **`authsome run -- `** — recommended. The proxy injects credentials without exposing secrets to the child process. +2. **`authsome export --format env`** — when the tool cannot route through an HTTP proxy. +3. **Daemon HTTP API** — when you are building tooling that talks to the local daemon over PoP-authenticated HTTP. - The supported integration surface for almost every workflow is the **CLI plus the proxy** (`authsome run -- `). The library exists for embedding authsome inside a larger Python orchestrator with custom storage, custom subprocess management, or per-call connection selection that the proxy can't yet do. If you're not in that case, the CLI is the right tool. See [Run agents with the proxy](/guides/run-agents-with-proxy). + The CLI plus proxy covers almost every workflow. Drop to export or the HTTP API only when embedding authsome in custom orchestration or non-Python runtimes. See [Run agents with the proxy](/guides/run-agents-with-proxy). ## Install @@ -22,176 +26,67 @@ uv pip install authsome Python 3.13 or newer. -## Quick start +## Quick start (proxy) -```python -from authsome.server.dependencies import create_auth_service +```bash +authsome init +authsome login github +authsome run -- python my_script.py +``` -auth = create_auth_service() -token = auth.get_access_token("github", connection="default") +Your script reads placeholder env vars; the proxy substitutes real credentials on outbound HTTP requests. No authsome import required in the script. -import httpx -r = httpx.get( - "https://api.github.com/user", - headers={"Authorization": f"Bearer {token}"}, -) -print(r.json()) +## Quick start (export) + +```bash +eval "$(authsome export github --format env)" +python -c 'import os; print(os.environ["GITHUB_ACCESS_TOKEN"][:8] + "...")' ``` -`create_auth_service(..., identity="")` is the same constructor the daemon uses after it has validated a registered identity handle. It reads `~/.authsome/config.json`, opens the vault scoped to that identity, wires the provider registry, and returns an `AuthService`. +Refresh is handled by the daemon. Re-run export when you need fresh values in a long-lived shell. -To target a non-default home directory: +## Quick start (daemon HTTP API) -```python -from pathlib import Path -from authsome.server.dependencies import create_auth_service +The CLI and proxy both call the daemon at `http://127.0.0.1:7998/api/...` with PoP JWT authentication. Every protected request carries `Authorization: PoP ` signed by the local Ed25519 identity key. -auth = create_auth_service(home=Path("/var/lib/authsome")) +```bash +curl -s http://127.0.0.1:7998/api/health | jq +curl -s http://127.0.0.1:7998/api/connections | jq ``` -## Public exports +See [HTTP daemon API](/reference/daemon-api) for every route. For programmatic PoP signing, follow `src/authsome/cli/client.py` in the repository — that client is the reference implementation. + +## Public package exports -Everything below is re-exported from the top-level `authsome` package: +The top-level `authsome` package re-exports models, errors, and the `Vault` interface for tests and advanced embedding: ```python from authsome import ( - AuthLayer, # building-block facade with vault, registry, identity, app_store - AuthService, # full auth + credential lifecycle service - Vault, # encrypted storage interface - - # Models - AuthType, ConnectionStatus, ExportFormat, FlowType, - ConnectionRecord, ProviderDefinition, Sensitive, - - # Errors (all subclass AuthsomeError) + Vault, + AuthType, + ConnectionRecord, + ConnectionStatus, + ExportFormat, + FlowType, + ProviderDefinition, + ProviderType, + Sensitive, AuthsomeError, AuthenticationFailedError, ConnectionNotFoundError, CredentialMissingError, - DiscoveryError, - EncryptionUnavailableError, - InputCancelledError, - InvalidProviderSchemaError, - ProfileNotFoundError, + IdentityNotFoundError, ProviderNotFoundError, RefreshFailedError, - StoreUnavailableError, TokenExpiredError, - UnsupportedAuthTypeError, - UnsupportedFlowError, ) ``` -## AuthService - -The class that owns OAuth flows, token refresh, and the login/logout/revoke lifecycle. It receives a `Vault`, a `ProviderRegistry`, and an `AppStore` as dependencies. For most library use, build it with `create_auth_service()` as shown above. - -### Get a token or API key - -```python -token = auth.get_access_token("github", connection="default") -key = auth.get_access_token("openai", connection="default") -``` - -`get_access_token` checks the stored expiry, refreshes the token if it's close to expiry (within 300 seconds), writes the fresh record back, and returns the usable string. For API-key providers the call returns the stored key value through the same code path. - -For pre-built headers ready to splice into a request: - -```python -headers = auth.get_auth_headers("github", connection="default") -# {"Authorization": "Bearer ghu_..."} -``` - -### Inspect connections - -```python -record = auth.get_connection("github", connection="default") - -record.status # ConnectionStatus enum: connected | expired | invalid | revoked | not_connected -record.scopes # list[str] -record.expires_at # datetime | None -record.account.id # provider-side account id -record.account.label # display name -``` - -Sensitive fields on the record are encrypted on disk and decrypted on read. - -### List and inspect providers - -```python -for definition in auth.list_providers(): - print(definition.name, definition.display_name, definition.auth_type, definition.flow) - -# Grouped by source ("bundled" / "custom") -by_source = auth.list_providers_by_source() - -# Single provider -definition = auth.get_provider("github") -definition.api_url -definition.oauth.scopes -``` - -### Manage connections - -```python -auth.set_default_connection("github", "work") -auth.logout("github", connection="personal") -auth.revoke("github") -auth.remove("github") -``` - -`logout` removes a single local connection. `revoke` calls the provider's revocation endpoint (where supported) and clears all connections + client credentials for the provider in the active profile. `remove` uninstalls the provider definition entirely (for custom providers) or resets it to the bundled default. - -### Run a login flow - -Most library users rely on the CLI for login because the flows need a browser or a TTY. To drive a flow programmatically: - -```python -from authsome.auth.sessions import AuthSession - -session = auth.begin_login_flow( - provider="github", - flow_type=FlowType.PKCE, - connection="default", -) -# Pop the browser, collect inputs, then: -auth.resume_login_flow(session) -``` - -The exact session shape depends on the flow type. For automation, prefer driving `authsome login` and reading its `--json` output. - -### Manage Principals and Identities - -CLI-level Principal and Identity switching is managed via `authsome init` and `authsome login`. The library provides programmatic access to these constructs, but typically you rely on the daemon resolving the active context. - -### Register a custom provider - -```python -from authsome import AuthService, ProviderDefinition - -definition = ProviderDefinition.model_validate_json(open("acmecrm.json").read()) -auth.register_provider(definition, force=False) -``` - -Equivalent to `authsome register ./acmecrm.json`. - -## AuthLayer - -A thin facade that holds the building blocks (`vault()`, `registry()`, `identity()`, `app_store()`). Useful when you need direct access to one component without going through the full `AuthService` surface . for example, reading a credential record without triggering refresh. - -```python -from authsome import AuthLayer - -layer = AuthLayer(vault=..., registry=..., app_store=..., identity="local") -vault = layer.vault() -record_bytes = vault.get("profile:local:github:connection:default") -``` - -For typical library use, `AuthService` is the right entry point. Drop down to `AuthLayer` and `Vault` directly only when you're embedding authsome inside a larger orchestrator with custom storage. +`CredentialService` (the daemon's credential lifecycle coordinator) lives in `authsome.server` and is constructed by the daemon's dependency injection layer. It is not a supported public embedding API. ## Vault -A minimal key-value interface with field-level encryption applied transparently: +A minimal encrypted key-value interface. Credential records are stored under keys like `vault:::connection:`. Direct vault access is rare outside tests: ```python vault.get(key) @@ -200,45 +95,40 @@ vault.delete(key) vault.list(prefix) ``` -Direct vault access is rare. Prefer `AuthService`; it manages encryption, decryption, and connection lifecycle for you. +Prefer the CLI or daemon API; they manage encryption, refresh, and Principal/Vault authorization for you. ## Errors -All exceptions subclass `AuthsomeError`. Common ones you'll catch: +All exceptions subclass `AuthsomeError`. Common ones: | Exception | When | |-----------|------| -| `ProviderNotFoundError` | `get_provider("does-not-exist")` | -| `ConnectionNotFoundError` | Requested connection doesn't exist on the provider | -| `CredentialMissingError` | Provider is registered but no connection has been completed | +| `ProviderNotFoundError` | Unknown provider name | +| `ConnectionNotFoundError` | Requested connection doesn't exist | +| `CredentialMissingError` | Provider registered but no completed connection | | `RefreshFailedError` | Provider rejected the refresh token | | `TokenExpiredError` | Token expired and refresh wasn't possible | -| `AuthenticationFailedError` | Login flow returned an error or the user cancelled | -| `InputCancelledError` | User cancelled credential entry | -| `StoreUnavailableError` | Vault file is locked or unreadable | -| `EncryptionUnavailableError` | OS keyring backend unreachable | -| `InvalidProviderSchemaError` | `register_provider` got a malformed `ProviderDefinition` | +| `AuthenticationFailedError` | Login flow failed or was cancelled | +| `IdentityNotFoundError` | Identity handle not registered with the daemon | +| `StoreUnavailableError` | Vault or store unreachable | Exit codes in [CLI reference](/reference/cli) map one-to-one to these classes. -## When to use the library vs the CLI - -| Use the library | Use the CLI | -|-----------------|--------------| -| Embedding authsome in an existing Python agent. | Driving authsome from any non-Python runtime. | -| Fine-grained per-call connection selection. | Default-connection model is enough. | -| Reading connection metadata without parsing CLI output. | `--json` output is enough. | -| Stubbing the vault or auth layer in tests. | You're a human running commands. | +## When to use which surface -For most agent workflows, `authsome run -- ` is simpler than embedding the library directly. The library exists for cases where the CLI shape doesn't fit. +| Use the proxy | Use export | Use the HTTP API | +|---------------|------------|------------------| +| Python/Node/any HTTP agent | SDKs that ignore proxies | Custom tooling on top of authsome | +| Secrets must not appear in env | Short-lived shell sessions | Non-Python orchestrators | +| Default for new integrations | TLS-pinned SDKs | Dashboards and automation | ## What's next - Where AuthService and Vault sit in the layered model. + Identity, Vault, Principal, and the daemon. - - Every command. The CLI is a client of the same code. + + Every route the daemon exposes. diff --git a/docs/site/troubleshooting/auth-errors.mdx b/docs/site/troubleshooting/auth-errors.mdx index 6acaa680..b527413f 100644 --- a/docs/site/troubleshooting/auth-errors.mdx +++ b/docs/site/troubleshooting/auth-errors.mdx @@ -59,7 +59,7 @@ authsome remove authsome login ``` -`remove` deletes provider state for the current profile, including any stored OAuth client credentials. The provider definition (bundled or custom) is unaffected. The next `login` triggers the browser form to collect fresh values. +`remove` deletes provider state for the current vault, including any stored OAuth client credentials. The provider definition (bundled or custom) is unaffected. The next `login` triggers the browser form to collect fresh values. ## Provider not connected at all @@ -74,7 +74,7 @@ If the provider isn't in the bundled set, register a custom definition first. Se ## Still failing - Run `authsome --verbose login ` to surface the full daemon round-trip and the exact provider response. -- Check `~/.authsome/audit.log` for the most recent action and outcome. +- Run `authsome log` to inspect recent audit events from the daemon. - See [Diagnose with doctor](/troubleshooting/doctor) for installation-level checks. - For HTTPS / TLS errors specifically, see [Proxy networking](/troubleshooting/proxy-networking). - For token-refresh internals, see [Token refresh](/troubleshooting/token-refresh). diff --git a/docs/site/troubleshooting/daemon-issues.mdx b/docs/site/troubleshooting/daemon-issues.mdx index 71462732..c6ebd0c4 100644 --- a/docs/site/troubleshooting/daemon-issues.mdx +++ b/docs/site/troubleshooting/daemon-issues.mdx @@ -75,7 +75,6 @@ If you do want a hosted daemon and it's unreachable, the fix is on the daemon ho - `AUTHSOME_BASE_URL` on the daemon matches the URL you're calling. - Ingress is allowed from your client's network (private VPC, VPN, or whatever the team uses). - ## Login was interrupted by a daemon restart Active auth sessions live in the daemon's memory. A restart loses them. The provider may or may not have accepted the authorization on its side. Re-run the login: diff --git a/docs/site/troubleshooting/doctor.mdx b/docs/site/troubleshooting/doctor.mdx index 897510fb..025243e7 100644 --- a/docs/site/troubleshooting/doctor.mdx +++ b/docs/site/troubleshooting/doctor.mdx @@ -1,44 +1,48 @@ --- title: "Diagnose with `doctor`" -description: "Run health checks on directory layout, encryption, and provider parsing, and read the output." +description: "Run health checks on the daemon, vault, and provider parsing, and read the output." --- -`authsome doctor` is the first command to run when something looks wrong. It walks the home directory layout, verifies encryption is available, and parses every provider definition. +`authsome doctor` is the first command to run when something looks wrong. It calls the daemon's `/api/ready` endpoint and reports subsystem status as JSON. ```bash authsome doctor ``` -A healthy machine prints `OK` for each check and exits with code `0`. +A healthy machine returns `"status": "ready"` and exits with code `0`. ## Checks performed | Check | What it verifies | |-------|------------------| -| Home directory | `~/.authsome` (or `AUTHSOME_HOME`) exists and is readable. | -| Master key | `master.key` exists with mode `0600`, or the OS keyring is reachable. | -| Profile store | `profiles//store.db` opens and is writable. | -| Lock file | `profiles//lock` is acquirable. | -| Provider parsing | Every JSON in `bundled_providers/` and `~/.authsome/providers/` validates against the schema. | -| Audit log | `audit.log` is writable. | +| `store` | The relational store (SQLite or Postgres) opens and passes a health probe. | +| `vault` | The encrypted KV store accepts a read/write roundtrip. | +| `integrity` | Vault integrity check succeeds for the active identity. | +| `identity` | The caller's identity is registered and authorized. | +| `providers` | Every bundled and custom provider definition parses. | +| `connections` | Connection records for the active vault load successfully. | +| `spec_version` | Server config schema version matches. | +| `redis` | Present only when `AUTHSOME_REDIS_URL` is set; pings the Redis backend. | + +Non-fatal observations appear in `warnings` (for example, no active provider connections yet). Fatal problems appear in `issues` and set `"status": "not_ready"`. ## Common failures ```text - [FAIL] Master key not found at ~/.authsome/server/master.key + vault: Master key not found at ~/.authsome/server/master.key ``` Causes: - You haven't initialized authsome on this machine. Run `authsome init` to provision the home directory, identity, and master key. - - You moved or deleted `~/.authsome`. If you have a backup, restore it. Without the master key, encrypted records cannot be decrypted. + - You moved or deleted `~/.authsome/server/`. If you have a backup, restore it. Without the master key, encrypted records cannot be decrypted. ```text - [FAIL] ~/.authsome/server/master.key has mode 0644 (expected 0600) + vault: ~/.authsome/server/master.key has mode 0644 (expected 0600) ``` Fix: @@ -48,9 +52,9 @@ A healthy machine prints `OK` for each check and exits with code `0`. ``` - + ```text - [FAIL] Provider 'acmecrm' failed to parse: missing required field 'token_url' + providers: Provider 'acmecrm' failed to parse: missing required field 'token_url' ``` A custom provider JSON in `~/.authsome/providers/` is malformed. Open the file, fix the indicated field, and re-run. @@ -58,32 +62,29 @@ A healthy machine prints `OK` for each check and exits with code `0`. ```text - [FAIL] Encryption mode is 'keyring' but no keyring backend is available + vault: Encryption mode is 'keyring' but no keyring backend is available ``` Causes: - - On Linux without a graphical session, the `keyring` library can't reach a backend. Switch to `local_key` mode by editing `~/.authsome/config.json`: - - ```json - { "encryption": { "mode": "local_key" } } - ``` - + - On Linux without a graphical session, the `keyring` library can't reach a backend. Switch to local file mode by editing `~/.authsome/client/config.json` or setting `AUTHSOME_MASTER_KEY`. - A required system package is missing. On Debian/Ubuntu: `sudo apt install gnome-keyring`. - + ```text - [FAIL] Could not acquire lock on profiles/default/lock + identity: Unknown identity handle ``` - Another authsome process is mid-write. Wait a few seconds and retry. If a stale lock persists (the previous process crashed): + Run `authsome init` to create a local identity, then complete the Principal claim flow at the URL the daemon prints. + - ```bash - rm ~/.authsome/profiles/default/lock + + ```text + Could not connect to daemon at http://127.0.0.1:7998 ``` - Only do this when you are certain no other authsome process is running. + The daemon is not running or `AUTHSOME_BASE_URL` points somewhere wrong. See [Daemon issues](/troubleshooting/daemon-issues). @@ -95,10 +96,10 @@ For deeper inspection of any command, enable verbose logging: authsome --verbose login github ``` -DEBUG logs go to stderr and to the rotating log file at `~/.authsome/logs/authsome.log`. Inspect the log: +DEBUG logs go to stderr and to the rotating log file at `~/.authsome/client/logs/authsome.log`. Inspect the log: ```bash -tail -f ~/.authsome/logs/authsome.log +tail -f ~/.authsome/client/logs/authsome.log ``` ## Reset to a clean slate @@ -107,7 +108,7 @@ If your install is irrecoverably broken and you don't have any credentials to pr ```bash rm -rf ~/.authsome -authsome whoami # triggers re-initialization +authsome init ``` This destroys every stored credential. You will need to log in to every provider again. diff --git a/docs/site/troubleshooting/token-refresh.mdx b/docs/site/troubleshooting/token-refresh.mdx index d9493e83..f97bd723 100644 --- a/docs/site/troubleshooting/token-refresh.mdx +++ b/docs/site/troubleshooting/token-refresh.mdx @@ -3,7 +3,7 @@ title: "Token refresh failures" description: "Diagnose why a stored OAuth2 token failed to refresh and recover the connection." --- -Authsome refreshes OAuth2 access tokens automatically. When you ask for a token (via `authsome get`, `export`, `run`, or the library `AuthLayer`), authsome checks the stored expiry. If the token is within ~5 minutes of expiring, it calls the provider's token endpoint with the stored refresh token, writes the fresh credentials back to the vault, and returns the new access token. +Authsome refreshes OAuth2 access tokens automatically. When you ask for a token (via `authsome get`, `export`, `run`, or the daemon API), authsome checks the stored expiry. If the token is within ~5 minutes of expiring, it calls the provider's token endpoint with the stored refresh token, writes the fresh credentials back to the vault, and returns the new access token. When refresh fails, the connection moves into one of two states. @@ -39,7 +39,7 @@ When refresh fails, the connection moves into one of two states. Error: refresh failed for : invalid_client ``` - The OAuth client credentials stored under your profile no longer match the provider. This usually means the OAuth app's client secret was rotated. + The OAuth client credentials stored in your vault no longer match the provider. This usually means the OAuth app's client secret was rotated. ```bash authsome revoke