Skip to content

DX: OAuth Login / Multi-Org Auth Management #76

Description

@alexhraber

Problem

builddeck currently requires BUILDKITE_API_TOKEN as an environment variable. This means:

  • First-run setup requires generating a token in the browser, then exporting it
  • Switching organizations requires a different token or re-auth
  • Token has no auto-refresh — if it expires, the TUI breaks until the user sources a new one
  • No built-in way to see which user/org you are authenticated as

The Buildkite CLI supports OAuth 2.0 PKCE login (bk auth login) that stores tokens in the OS keyring or /dev/shm, supports multi-org switching, and auto-refreshes expired tokens.

Proposed Feature

Add a first-run auth wizard and in-TUI login flow:

1. First-Run Auth Wizard

When no token is found (no env var, no stored credentials), instead of exiting with an error, show an interactive welcome screen:

┌──────────────────────────────────────┐
│  Welcome to builddeck 🃁              │
│                                       │
│  You need a Buildkite API token       │
│  to get started.                      │
│                                       │
│  [1] Log in with browser (OAuth)      │
│  [2] Paste an API token               │
│  [3] Use BUILDKITE_API_TOKEN env var   │
│                                       │
│  (press 1, 2, or 3)                   │
└──────────────────────────────────────┘

2. OAuth Login Flow

For option 1 (or bk auth login equivalent):

  1. Open browser to Buildkite OAuth authorization URL (PKCE)
  2. Show a waiting overlay with instructions
  3. On callback, exchange code for token
  4. Store token in credential store (OS keyring or ~/.config/builddeck/credentials)
  5. Store refresh token for auto-refresh
  6. Navigate to org list

3. In-TUI Org Switcher

Add an org switcher overlay (keybinding: Shift+A or via the org list) that:

┌──────────────────────────────────────┐
│  Switch Organization                  │
│                                       │
│  Current: my-org                      │
│                                       │
│  ┌───────────────────────────────┐   │
│  │ ◎ my-org (current)           │   │
│  │ ○ other-org                  │   │
│  │ ○ third-org                  │   │
│  │ ○ [+ Add Organization]      │   │
│  └───────────────────────────────┘   │
│                                       │
│  [enter] switch  [A] add org         │
└──────────────────────────────────────┘

4. Auth Status

Show current auth context somewhere accessible (e.g. in the stats overlay or a dedicated ? panel):

  • Current org slug
  • Token scopes
  • Token expiry (if OAuth)
  • User name / email

Why this fits a TUI

  • First-run wizard removes the biggest onboarding friction (no browser trip to generate a token)
  • OAuth login from the TUI is more polished than env var setup
  • Org switching without restarting is a natural fit for the orgs pane
  • Credential store avoids leaking tokens in shell history or .env files

Security

  • Credential store: OS keyring preferred; fallback to encrypted file in ~/.config/builddeck/ (not world-readable)
  • OAuth PKCE: Code challenge + verifier, no client secret needed
  • Token refresh: Refresh transport transparently re-auths when token expires
  • Fallback: BUILDKITE_API_TOKEN env var still works and takes precedence

References

  • bk auth login in buildkite/cli
  • OAuth 2.0 PKCE (RFC 7636)
  • Buildkite OAuth API

Acceptance

  • First-run wizard replaces the "BUILDKITE_API_TOKEN not set" fatal exit
  • OAuth login flow from TUI opens browser and waits for callback
  • Token paste option accepts and validates a token inline
  • Credential store persists tokens across restarts
  • Org switcher allows switching without restart
  • Auth status shows current user/org/scopes
  • BUILDKITE_API_TOKEN env var still takes precedence
  • Token refresh handled transparently

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions