Skip to content

feat: add device authorization flow (RFC 8628) for CLI auth#61

Merged
NormallyGaussian merged 3 commits intomainfrom
feat/device-auth
Mar 11, 2026
Merged

feat: add device authorization flow (RFC 8628) for CLI auth#61
NormallyGaussian merged 3 commits intomainfrom
feat/device-auth

Conversation

@NormallyGaussian
Copy link
Copy Markdown
Contributor

@NormallyGaussian NormallyGaussian commented Mar 11, 2026

Summary

  • Adds OAuth Device Authorization Grant (RFC 8628) to enable authentication in environments that cannot open a browser — SSH sessions, containers, CI, Claude Desktop/Web
  • parallel-cli login --device shows verification URL + user code, polls until approved
  • parallel-cli login --device --json emits NDJSON: first line has verification_uri_complete + user_code for agents to present, second line confirms authenticated
  • Auto-detects headless environments (SSH, CI, Docker, no display) and uses device flow automatically
  • Exposes request_device_code() / poll_device_token() as public Python API for SDK users who need full control
  • Integrates with server-side endpoints shipped in shapleyai/code#12392

Agent usage

parallel-cli login --device --json

Output is two newline-delimited JSON objects. The first is emitted immediately with the device code info:

{"status": "waiting_for_authorization", "verification_uri": "https://platform.parallel.ai/getKeys/device", "verification_uri_complete": "https://platform.parallel.ai/getKeys/device?user_code=BCDF-GHJK", "user_code": "BCDF-GHJK", "expires_in": 600}

The agent should:

  1. Parse the first JSON line
  2. Present verification_uri_complete as a clickable link to the user (this URL has the code pre-filled)
  3. Also show user_code in case the user needs to enter it manually
  4. Wait for the command to complete

Once the user approves in the browser, the second line is emitted and the command exits:

{"status": "authenticated"}

Example: Claude Code / AI agent integration

Agent runs: parallel-cli login --device --json
Agent reads first line of stdout → parses JSON
Agent tells user: "Please visit https://platform.parallel.ai/getKeys/device?user_code=BCDF-GHJK to authorize"
User clicks link, approves in browser
Command completes, agent reads second line → {"status": "authenticated"}
Agent confirms: "Authentication successful!"

Test plan

  • 587 tests passing (19 new tests for device flow)
  • Pre-commit hooks passing (ruff, ty)
  • Verified parallel-cli login --device end-to-end against production
  • Verified parallel-cli login --device --json emits correct NDJSON against production

Enables authentication in environments that cannot open a browser
(SSH, containers, CI, Claude Desktop/Web) via the device code flow.

- `parallel-cli login --device` for human-readable output
- `parallel-cli login --device --json` emits NDJSON for AI agents
- Auto-detects headless environments and uses device flow automatically
- Public Python API: request_device_code() / poll_device_token()
On CI (CI=true), _is_headless() returns True so get_api_key calls
_do_device_flow instead of _do_oauth_flow. Without mocking both,
the test hits the real endpoint and blocks forever.
On Linux CI (no DISPLAY env var), _is_headless() returns True via
the display check even after clearing SSH/CI/container vars. Tests
that assert non-headless behavior need DISPLAY set explicitly.
@NormallyGaussian NormallyGaussian merged commit e6c9dc9 into main Mar 11, 2026
7 checks passed
@NormallyGaussian NormallyGaussian deleted the feat/device-auth branch March 11, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant