Capgo · Engineering
OAuth Device Flow shape · who talks to whom, and in what order
sequenceDiagram
autonumber
actor Dev as Developer
participant CLI as CLI (terminal)
participant BE as Capgo Backend
participant Web as Browser (logged in)
Dev->>CLI: runs `capgo login`
CLI->>BE: POST /cli-auth/start (device name)
BE-->>CLI: device_code (secret) + user_code
"enjoy-enough-outwit-win" + verify URL
CLI-->>Dev: prints the phrase to confirm
CLI->>Web: opens the verify URL
rect rgb(238,245,255)
note over CLI,BE: CLI quietly polls in the background
loop every few seconds
CLI->>BE: POST /cli-auth/poll (device_code)
BE-->>CLI: "authorization_pending"
end
end
Web->>BE: GET /cli-auth/session [JWT]
BE-->>Web: device info + the same phrase
Dev->>Web: confirms phrase matches,
picks org / app / permission
Web->>BE: POST /cli-auth/authorize [JWT]
BE->>BE: check permission + create key NOW (hashed),
stash one-time encrypted secret
BE-->>Web: success → "return to your terminal"
CLI->>BE: POST /cli-auth/poll (device_code)
BE-->>CLI: "authorized" + api_key (delivered once)
secret burned, session destroyed
CLI->>CLI: save key to ~/.capgo
CLI-->>Dev: "Logged in!"
flowchart LR
Dev([Developer]) -->|runs capgo login| CLI[CLI · terminal]
CLI <-->|device_code secret
start + poll| BE[(Capgo Backend)]
CLI -->|opens browser| Web[Browser page]
Web <-->|JWT session
session + authorize| BE
BE -->|mint NEW key| Key{{New API key}}
Key -.delivered once over HTTPS.-> CLI
classDef cli fill:#eef5ff,stroke:#119eff,color:#0c6eb8;
classDef be fill:#eef0f7,stroke:#515271,color:#515271;
classDef web fill:#e8f7f4,stroke:#1FB2A5,color:#0e8a7e;
classDef key fill:#fff4e8,stroke:#ff7211,color:#b8480a;
class CLI cli; class BE be; class Web web; class Key key;
The CLI talks to the backend with a one-time device_code secret (it isn't logged in). The browser talks to the backend with the developer's JWT (their existing dashboard login). The backend is the bridge: the logged-in browser authorises, and the key flows back to the waiting terminal.