a2aproject / a2aproject/a2a-rs

a2acli: auth login — OAuth 2.1 device-code, client-credentials, and token storage

Abierto
#188 0 comentarios 0 reacciones 0 asignados Ver en GitHub
enhancement
Lenguaje dominante
Rust
Estrellas
75
Forks
19
Merge medio
11 h 27 min
PR fusionados (30 d)
21

Descripción

Part of #181 (Tier 2). **Phase 2 — surface not yet defined upstream.** Largest item in the tier.

## Summary

Three requirements, one command (§12.2):

| ID | Requirement |
| --- | --- |
| `A2ACLI_AUTH_005` | `auth login` — OAuth 2.1 device-code flow |
| `A2ACLI_AUTH_006` | `auth login` — OAuth 2.1 client-credentials flow |
| `A2ACLI_AUTH_007` | Secure token storage with automatic attachment on later calls |

`a2acli` has no `auth` command. Tier 1 credentials are caller-supplied only: `--bearer`, `--api-key`, `--svc-param` and their env equivalents (#176).

The device-code flow ([RFC 8628](https://www.rfc-editor.org/rfc/rfc8628)) is the one the spec calls out as *"designed for input-constrained clients such as a CLI"*.

## Why

Today the caller must obtain a token by some other means and pass it in. That is fine for CI with a service credential, but for a person at a terminal against an OAuth-protected agent there is no path at all.

## Tension with the agent-first principle, worth resolving explicitly

§6.1 requires **no interactive prompts** in the default path, and §8.3 requires the tool to persist *configuration, never session state*. A login command sits awkwardly against both:

- Device-code is interactive by nature — it prints a URL and a code and waits. It should therefore be confined to `auth login` and never triggered implicitly by another command, so `send` and `task get` stay unattended-safe.
- A stored access token is closer to session state than configuration. §8.3's prohibition targets `taskId`/`contextId` replay specifically, and `AUTH_007` explicitly requires storage, so storing a token is sanctioned — but the boundary should be stated in the implementation, not assumed.

## Surface to agree first

The Go CLI has no `auth` command, so there is **nothing to conform to**. Open questions for upstream:

- where the OAuth endpoints come from: the Agent Card's `securitySchemes` (A2A §4.5.2), or explicit flags?
- token storage location and mechanism: OS keychain versus a mode-`0600` file under `~/.config/a2a-cli/`. A keychain is more defensible but adds a platform-specific dependency and behaves badly in headless CI — exactly where a CLI runs.
- `auth logout` / `auth status`: neither is in §7.1's command table, but stored credentials with no way to inspect or clear them is a poor security posture.
- refresh-token handling and what happens when refresh fails mid-command.

## Scope (pending the above)

- [ ] Agree the surface upstream in `a2a-cli`; record the outcome here.
- [ ] `auth login` with the device-code flow: display the verification URI and user code, poll the token endpoint honoring the server's `interval` and `slow_down` per RFC 8628 §3.5, and respect `--timeout`.
- [ ] `auth login` with the client-credentials flow, for unattended use.
- [ ] Secure token storage, automatically attached to later calls, with explicit precedence against `--bearer`/`A2ACLI_BEARER` — an explicit flag must still win (§6.5).
- [ ] Warn if the token store is readable by other users, matching the existing `.env` warning from #177.
- [ ] Never log token material, including under `--debug` wire logging (`A2ACLI_AUTH_004`; see #183).
- [ ] `config show` reports whether a stored token is present and its source, redacted — never the value (the existing `(set, redacted)` form).
- [ ] Device-code must not be reachable from any non-`auth` command, so the default path stays non-interactive (§6.1).
- [ ] Tests: both flows against a fixture authorization server; `slow_down` honored; an expired token refreshed; `--bearer` overriding a stored token; no token material in `--debug` output.

## Requirements closed

`A2ACLI_AUTH_005`, `A2ACLI_AUTH_006`, `A2ACLI_AUTH_007` (§12.2)

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.