Skip to content

feat(login): standards RFC 8628 device login for Hanzo IAM - #4

Merged
zeekay merged 1 commit into
mainfrom
feat/hanzo-oidc-device
Jun 28, 2026
Merged

feat(login): standards RFC 8628 device login for Hanzo IAM#4
zeekay merged 1 commit into
mainfrom
feat/hanzo-oidc-device

Conversation

@zeekay

Copy link
Copy Markdown
Member

What

dev login --device-auth (default provider hanzo) now speaks the standard OAuth 2.0 Device Authorization Grant (RFC 8628) against Hanzo IAM, so headless/CLI login works on hanzo.id / lux.id / zoolabs.id.

Previously --device-authalways used OpenAI's proprietary /api/accounts/deviceauth + PKCE scheme (it ignored --provider), which Hanzo IAM does not serve — the genesis of the expected value at line 1 column 1 failure when signing into Hanzo ID.

Changes

  • login/src/oidc_device_auth.rs (new) — brand-agnostic RFC 8628 flow: POST {issuer}/oauth/device, then poll {issuer}/oauth/token with grant_type=urn:ietf:params:oauth:grant-type:device_code, handling authorization_pending / slow_down (interval backoff) / access_denied / expired_token. Prefers verification_uri_complete for one-click approval. Persists via the same token store the browser flow uses. Pure classify_poll() is unit-tested.
  • --device-auth routes by providerhanzo (default) → RFC 8628; openai → the existing OpenAI device scheme (untouched); claude → guidance (API-key only).
  • HANZO_CLIENT_IDhanzo-devhanzo-apphanzo-dev returns Invalid client_id live; hanzo-app is the canonical <org>-<app> client that responds on hanzo.id. issuer/client overridable via the experimental flags for lux-app/zoo-app.

Tests

  • 8 unit tests (interval clamp/defaults, lifetime, link selection, IAM response parse, poll classification incl. all error codes) — pass
  • cargo check -p codex-login -p codex-cli clean; clippy -p codex-login clean

Depends on

hanzoai/iam feat/device-code-login — the IAM must have device_code re-enabled and the <org>-app clients granted device_code for the end-to-end flow to complete. Code-complete + contract-verified on both sides; release dev after the IAM deploy.

`dev login --device-auth` (default provider hanzo) now speaks standard
OAuth 2.0 Device Authorization Grant against Hanzo IAM, so headless/CLI
login works on hanzo.id / lux.id / zoolabs.id. Previously --device-auth
always used OpenAI's proprietary /api/accounts/deviceauth + PKCE scheme
(ignoring --provider), which Hanzo IAM does not serve — the genesis of
the "expected value at line 1 column 1" failure.
- oidc_device_auth.rs: brand-agnostic RFC 8628 flow. POST {issuer}/oauth/
device, then poll {issuer}/oauth/token with grant_type=device_code,
handling authorization_pending / slow_down (interval backoff) /
access_denied / expired_token. Both interval AND expires_in are clamped
(a hostile issuer can't overflow Instant+Duration or pin the poll).
Prefers verification_uri_complete. Persists via the same token store
the browser flow uses. Pure classify_poll() is unit-tested (8 tests).
- device-auth routes by provider: hanzo (default) -> RFC 8628; openai ->
the existing OpenAI device scheme (untouched); claude -> guidance.
- HANZO_CLIENT_ID hanzo-dev -> hanzo-app (hanzo-dev returns Invalid
client_id live; hanzo-app is the canonical <org>-app client). issuer/
client overridable via the experimental flags for lux-app/zoo-app.
Verified: cargo check (login+cli), clippy clean, 8 unit tests pass.
@zeekay
zeekay merged commit b519778 into mainJun 28, 2026
5 of 20 checks passed
Sign up for freeto 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

@zeekay