Skip to Content

API key vs OAuth

Two ways to authenticate to CMDOP — pick by who’s calling and how often.

TL;DR

Use casePick
Interactive human (terminal, desktop)OAuth
CI / unattended agentWorkspace API key
Bot / scheduled scriptWorkspace API key
SDK during developmentOAuth (your login)
SDK in productionWorkspace API key
Mixed (script today, you tomorrow)Both — resolver picks

OAuth

OAuth tokens come from cmdop login (device flow). Properties:

  • Identity — your personal account.
  • Workspaces — every workspace you belong to.
  • Lifetime — short access token (typically 1 hour) auto-refreshed 5 minutes before expiry.
  • Storagetoken_<mode>.json in CMDOP’s config dir (token_prod.json, token_dev.json).
  • Revocation — sign out, rotate the OAuth secret, or wait for refresh expiry.

OAuth is the right pick when a human is around to walk through device flow and the action is “yours” in the audit log.

Workspace API key

API keys are long-lived bearer tokens scoped to one workspace. Properties:

  • Identity — the workspace, plus a name you set at creation.
  • Workspaces — exactly one.
  • Lifetime — never expires unless you set an expiry. Defaults to “no expiry” — set one anyway if you can.
  • Storagessh_workspaces.json (mode 0600).
  • Revocation — explicit revoke from Workspace settings.

API keys survive member churn — a CI pipeline does not break because someone left the company.

Side by side

PropertyOAuth tokenWorkspace API key
Bound toPersonWorkspace
Multi-workspaceYesNo (one key per workspace)
RefreshAutomatic (5 min before expiry)None — long-lived
Setup timeDevice flow + browserCabinet click → copy secret
RevokeLogout / rotateCabinet → revoke
Best forHumansMachines
Audit attribution[email protected]apikey:gha-deploy

Credential resolver order

When you run cmdop ..., the resolver picks credentials in this order (internal/connect/workspace/Resolver.ResolveCtx):

  1. --api-key flag (explicit per-call override).
  2. CMDOP_API_KEY environment variable.
  3. --workspace=<name> flag — uses the named workspace’s stored key.
  4. Active workspace key from ssh_workspaces.json.
  5. Legacy cfg.Chat.GrpcAPIKey (one-shot migration).
  6. OAuth access token (fallback — “just works”).

Each Source is tagged in error messages so you know what was picked when something fails.

Rotating an API key without downtime

  1. Issue a new key with the same scopes in the cabinet.
  2. Roll the new value out to consumers (CI secret, deployment env).
  3. Watch audit log for the old key’s last use.
  4. Once you see the new key in audit (and the old key idle), revoke the old key.

Mixing in CI

Common pattern:

# In CI, where humans aren't around: export CMDOP_API_KEY="<workspace key>" cmdop connect prod-1 exec 'systemctl status myapp' # At your desk: unset CMDOP_API_KEY cmdop login # OAuth cmdop connect prod-1 exec 'systemctl status myapp'

The resolver prefers the env var, so CI uses the API key and your laptop falls back to OAuth.

API keys are workspace-bound. To use machines in workspace B you need a key for workspace B (or sign in with OAuth as a member of B).

Last updated on