# Authentication

The CLI supports two authentication methods: interactive login for development and API keys for CI/CD.

## Interactive Login (Recommended)

The CLI uses [OAuth 2.0 Device Authorization](https://datatracker.ietf.org/doc/html/rfc8628) to authenticate:

```bash
quickback login
```

A code is displayed in your terminal. Approve it in your browser and you're authenticated. See the [CLI Reference](/compiler/cloud-compiler/cli#login) for the full flow.

Credentials are stored at `~/.quickback/credentials.json` and include your session token, user info, and active organization.

## API Key (CI/CD)

For non-interactive environments (CI/CD, scripts), use an API key:

```bash
QUICKBACK_API_KEY=your_api_key quickback compile
```

Create API keys from your [Quickback account](https://account.quickback.dev/profile). Each key is scoped to your organization.

The API key takes precedence over stored credentials from `quickback login`.

## How Tokens Are Validated

The compiler-cloud worker validates authentication by forwarding your token to the Quickback API's `/internal/validate` endpoint via a [Cloudflare service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/). This resolves both session tokens (from `quickback login`) and API keys (from `QUICKBACK_API_KEY`).

## Credential Storage

Credentials are stored at `~/.quickback/credentials.json`:

```json
{
  "token": "...",
  "user": {
    "id": "...",
    "email": "paul@example.com",
    "name": "Paul Stenhouse",
    "tier": "free"
  },
  "expiresAt": "2026-02-16T01:42:21.519Z",
  "organization": {
    "id": "...",
    "name": "Acme",
    "slug": "acme"
  }
}
```

Sessions expire after 7 days. Run `quickback login` again to re-authenticate.

## Organizations

After login, the CLI auto-selects your organization:
- **One organization** — automatically set as active.
- **Multiple organizations** — you're prompted to choose one.

The active organization is stored in your credentials and sent with compile requests, so the compiler knows which org context to use.
