Skip to content

feat(cli): OAuth authentication flow via browser #699

@HugoRCD

Description

@HugoRCD

Context

Currently the CLI authenticates via a manually generated API token that the user must copy from the web UI (/user/tokens) and paste into the terminal. This works but adds friction to the onboarding experience.

An OAuth flow via browser would allow users to authenticate with a single command — the CLI opens the browser, the user logs in (or is already logged in), and the token is sent back to the CLI automatically.

Note: This depends on migrating the auth layer to Better Auth first, which provides built-in support for device/CLI OAuth flows.

Current auth flow

  1. User generates a token manually on the web UI
  2. shelve login → prompts for token (password input)
  3. Token is validated against /api/user/me
  4. Token + user info saved to ~/.shelve via rc9

Proposed OAuth flow

  1. shelve login → starts a local HTTP server on a random port
  2. Opens the browser to {SHELVE_URL}/cli/auth?port={port}
  3. User authenticates on the web (or is already logged in)
  4. Web app redirects to http://localhost:{port}/callback?token={token}
  5. CLI receives the token, validates it, saves to ~/.shelve
  6. Local server shuts down, CLI shows success message

Fallback

Keep the current manual token flow as a fallback:

  • shelve login → OAuth flow (default)
  • shelve login --token → manual token input (current behavior)

Implementation details

CLI side (packages/cli/)

  • Add a local HTTP server (lightweight, e.g. node:http) in BaseService.getToken()
  • Find an available port dynamically
  • Handle the callback route to extract the token
  • Add a timeout (e.g. 60s) with a clear error message
  • Open the browser using a cross-platform utility (open package or similar)

Web side (apps/shelve/)

  • Add a /cli/auth page that:
    • Ensures the user is authenticated
    • Generates a short-lived token scoped to CLI usage
    • Redirects to http://localhost:{port}/callback?token={token}
  • Consider security: validate the port parameter, use a one-time code exchange

Dependencies

  • Better Auth migration (for cleaner token management and potential device flow support)

Security considerations

  • The local callback server should only accept connections from localhost
  • Token exchange should be one-time use
  • Consider using PKCE or a state parameter to prevent interception
  • Short-lived authorization code exchanged for a longer-lived token

Metadata

Metadata

Assignees

No one assigned

    Labels

    clifeatureNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions