> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rogeriq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Device authorization

OAuth-style device flow for CLIs, desktop apps, and AI agents that can't bundle an API key.

# Device authorization flow

The device flow lets an interactive client (CLI, desktop app, IDE
extension) obtain an API key without ever handling the user's password
or asking them to copy-paste a key.

This is what powers `rogeriq auth login`. Use it when shipping any
client that runs on a user's machine.

## Endpoints

| Method | Path | Auth | Purpose |
|--------|------|------|---------|
| `POST` | `/api/auth/device/code` | none | Mint a device + user code. Rate-limited 5/min/IP. |
| `GET` | `/api/auth/device/lookup?user_code=XXXX-XXXX` | session | Dashboard fetches client name + status. |
| `POST` | `/api/auth/device/authorize` | session | User approves. Mints the API key. Rate-limited 10/min/user. |
| `POST` | `/api/auth/device/deny` | session | User rejects. |
| `POST` | `/api/auth/device/token` | none | Client polls. Returns the key once approved. Rate-limited 12/min/code. |

## The flow

**Client requests a code**

```bash
    curl -X POST https://api.rogeriq.com/api/auth/device/code \
      -H "Content-Type: application/json" \
      -d '{"client_name": "rogeriq-cli (sean@laptop)"}'
    ```

    Response:

    ```json
    {
      "device_code": "abc...48chars...",
      "user_code": "ABCD-1234",
      "verification_uri": "https://rogeriq.com/device",
      "verification_uri_complete": "https://rogeriq.com/device?code=ABCD-1234",
      "expires_in": 900,
      "interval": 5
    }
    ```

    The `user_code` uses an unambiguous alphabet (no O/0/I/1/L).

  **Client displays the code + opens browser**

Print the code to the terminal and try to open
    `verification_uri_complete` in the user's default browser. Always
    print the URL too — SSH / headless boxes can't auto-open.

  **User approves in the browser**

On rogeriq.com/device the user picks an org (auto-selected if they
    belong to one) and clicks **Authorize**. The dashboard calls
    `POST /api/auth/device/authorize`.

  **Client polls for the key**

```bash
    curl -X POST https://api.rogeriq.com/api/auth/device/token \
      -H "Content-Type: application/json" \
      -d '{"device_code": "abc..."}'
    ```

    Until the user approves, returns `202` with `code: AUTHORIZATION_PENDING`.

    On approval, returns the API key **once**:

    ```json
    {
      "access_token": "riq_a1b2c3d4...",
      "token_type": "bearer",
      "api_key": "riq_a1b2c3d4...",
      "org_id": "org_xxxxx",
      "scopes": ["read", "write"]
    }
    ```

    The device record is deleted on first successful read — a second poll
    returns `410 EXPIRED_TOKEN`. Store the key immediately.

## Status codes from `/device/token`

| Status | `code` | Meaning |
|-------:|--------|---------|
| 200 | (none) | Key returned. Store and stop polling. |
| 202 | `AUTHORIZATION_PENDING` | Keep polling. Respect `interval`. |
| 403 | `ACCESS_DENIED` | User pressed "Deny". Stop polling. |
| 410 | `EXPIRED_TOKEN` | Device code expired or already consumed. Restart the flow. |
| 429 | `SLOW_DOWN` | Polling too fast. Double your interval. |

## Polling interval

Start at the server-suggested `interval` (5s). If you receive `429
SLOW_DOWN`, double it. Respect any `interval` value in the 429 body.

## Security model

- Device codes carry 240 bits of entropy (48 chars × log₂(36)).
- User codes are 8 chars from a 31-char alphabet ≈ 40 bits — short
  enough to type, long enough to defeat brute force given the 5/min/IP
  limit at code generation and 12/min/code at polling.
- Single-use enforcement: the reverse lookup (`user_code → device_code`)
  is deleted **before** the API key is minted, preventing concurrent
  authorize calls from racing. The device record is deleted on first
  successful token poll.
- Codes expire after 15 minutes regardless of activity.
- All generation uses `crypto.getRandomValues()` (not `Math.random()`).

## Reference implementation

The [`rogeriq auth login`](/cli/auth) command is the reference
implementation. The polling loop, browser-open fallback, and SLOW_DOWN
backoff handling are in `cli/src/lib/device-auth.ts` (shipped in the
`@rogeriq/cli` npm tarball).