ADR-0010: grm CLI uses OAuth 2.0 Device Flow with long-lived API key storage

Status

Accepted

Tags

cli, grm, oauth2, device-flow, api-key, authentication, better-auth

Decision

grm auth login uses the OAuth 2.0 Device Authorization Grant (RFC 8628). The CLI requests a device code, opens the browser to the admin panel’s /device page where the user explicitly approves, then polls for an access token. Once received, the access token is immediately exchanged for a long-lived API key via Better Auth’s apiKey plugin. Only the API key is persisted to ~/.config/grm/config.json. The access token is discarded.

Why

The CLI must authenticate on behalf of developers and AI agents — including cases where no human is present after initial login. Alternatives rejected:
  • Username/password flags — requires typing credentials into the terminal, incompatible with SSO/OAuth, stores a password at rest.
  • Session cookie — browser-scoped, cannot be portably persisted across CLI invocations.
  • Store the access token — access tokens are short-lived; agents would need to re-authenticate mid-task with no human present to approve.
Storing an API key means every subsequent CLI invocation sends x-api-key with no expiry concern, and the key can be named and revoked independently per device.

Flow

grm auth login
  → POST /api/auth/device/code {client_id: "grm-cli"}
  ← {device_code, user_code, verification_uri, interval}
  → open browser to verification_uri
  → poll POST /api/auth/device/token every `interval` seconds
  ← {access_token} on user approval
  → POST /api/auth/api-key/create with Authorization: Bearer <access_token>
  ← {key: "ak_..."}
  → write {base_url, api_key} to ~/.config/grm/config.json
  → GET /api/auth/me with x-api-key to confirm and print email

Device approval page

The /device page in the admin panel requires an active session and shows explicit Approve and Deny buttons — it does not auto-approve on mount. Auto-approving silently on load would allow a stolen user_code link to approve a device without the user’s awareness.

Rules for agents

  • Never store the access token to disk — exchange it for an API key immediately and discard
  • The device page must require a confirmed session before rendering Approve/Deny
  • grm auth whoami authenticates via x-api-key header, not Bearer token
  • Config file permissions must be 0600 (owner read/write only)