Skip to content

CLI: add auth login + silent token refresh (builder-auth) to remove manual JWT copy #5

Description

@mrgoonie

Problem

Admin/CMS commands (me, media, knowledge, tag, org, …) authenticate with a bearer JWT only. Today users must copy that JWT by hand out of the admin UI's browser session into config set token. The JWT expires in ~7 days, so this repeats constantly. Painful and error-prone.

There is no auth command in the CLI — it's a UX gap, not a backend limitation.

Building blocks already exist (builder-auth)

The admin web never copies JWTs by hand — it calls the separate builder-auth service. Endpoints observed in admin-react/deploy/runtime-proxy.mjs:

Endpoint Body Returns
POST /v1/auth/login/email (or /login/username) { email/username, password } { data: { accessToken, refreshToken } }
POST /v1/auth/refresh { refreshToken } new { accessToken, refreshToken } (rotating)
POST /v1/auth/logout Bearer accessToken revokes
  • accessToken = the 7-day CMS JWT; refreshToken ~30-day.
  • No MFA in this flow (email + password).
  • Base URL is separate from the CMS API. Staging: https://auth-worker.core-f0d.workers.dev (BUILDER_AUTH_BASE_URL, per admin-react/wrangler.jsonc).

Proposed scope (interactive users; no backend change)

  1. agentbrain auth login — prompt email + password at the terminal (never store the password), POST /v1/auth/login/email, store accessToken + refreshToken in ~/.agentbrain/config.json (already chmod 600).
  2. Silent refresh: on a CMS 401, POST /v1/auth/refresh, persist the rotated pair, retry the request once. Falls back to a clear "run auth login" message when refresh fails.
  3. agentbrain auth logoutPOST /v1/auth/logout + clear stored tokens.
  4. New config key authUrl (default the builder-auth base; overridable via AGENTBRAIN_AUTH_URL / --auth-url), plus refreshToken storage (secret, masked in config list).
  5. auth status / whoami convenience (reuse GET /v1/me).

Out of scope (separate issue)

  • Headless/CI auth. Refresh tokens rotate (unusable as a static CI secret) and sk_ API keys can't reach CMS (verified: X-API-Key/Bearer sk_ → 401 on /cms/*). Needs a backend decision — builder-auth machine-token / api-key→accessToken exchange (preferred), or scoped API-key auth on admin routes. File as a backend question.

Acceptance criteria

  • auth login → subsequent me get / knowledge list succeed with no manual config set token.
  • Expired access token auto-refreshes transparently on the next command.
  • Password never written to disk; tokens stored 0600 and masked in config list.
  • Unit tests for login/refresh/logout + the 401→refresh→retry path.

Context

Surfaced during the live-backend smoke test (see PR #4). Auth-model evidence: agent-brain/backend-go CMS uses JWT session (mw.Auth); /mcp uses APIKeyWithOrg; builder-auth verifies api-keys at /v1/api-keys/verify but that path does not grant CMS access.

Open questions

  • Does builder-auth support a non-rotating / long-lived token for automation? (drives the CI issue)
  • Username vs email identifier mode — expose both login/email and login/username?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions