Skip to content

feat: add Device Authorization Grant (RFC 8628) as login fallback#60

Open
pavlo-v-chernykh wants to merge 2 commits intogleanwork:mainfrom
pavlo-v-chernykh:feature/device-authorization-flow
Open

feat: add Device Authorization Grant (RFC 8628) as login fallback#60
pavlo-v-chernykh wants to merge 2 commits intogleanwork:mainfrom
pavlo-v-chernykh:feature/device-authorization-flow

Conversation

@pavlo-v-chernykh
Copy link
Copy Markdown

@pavlo-v-chernykh pavlo-v-chernykh commented Mar 29, 2026

Summary

  • Adds OAuth 2.0 Device Authorization Grant (RFC 8628) as a fallback when the standard Authorization Code + PKCE flow fails (e.g. when DCR is unavailable with external IdPs like Okta)
  • Login strategy: auth code + PKCE → device flow → API token prompt
  • Parses glean_device_flow_client_id and device_authorization_endpoint from Glean's protected resource metadata and OIDC/RFC 8414 discovery

Changes

  • internal/auth/auth.go — refactored Login() into tryAuthCodeLogin + device flow fallback chain; extracted saveAndPrintToken helper that persists both tokens and client credentials for refresh
  • internal/auth/discovery.go — added glean_device_flow_client_id to protected resource metadata
  • internal/auth/device.go — new file implementing RFC 8628: device code request, token polling with slow_down interval backoff, input validation (URL scheme, interval/expiry clamping, empty token rejection)
  • internal/auth/device_test.go — 14 tests covering happy path, error cases, polling states, interval clamping, and context cancellation
  • internal/auth/discovery_test.go — added test for glean_device_flow_client_id parsing
  • README.md + snippets/readme/snippet-04.sh — updated auth docs to mention device flow

Test plan

  • go test -race ./... passes
  • golangci-lint run reports 0 issues
  • markdown-code check confirms docs in sync
  • Tested end-to-end against Okta SSO — device flow login + Glean API calls working

@steve-calvert-glean
Copy link
Copy Markdown
Collaborator

steve-calvert-glean commented Apr 4, 2026

Hey @pavlo-v-chernykh — thanks for this PR! The RFC 8628 implementation is solid: the polling logic, slow_down handling, interval clamping, and test coverage are all well done.

We've been going back and forth on whether to merge this right now, and wanted to be transparent about the hesitation. The core challenge is that Glean's own OAuth authorization server doesn't support the device code flow today. The PR correctly gates activation on the server advertising glean_device_flow_client_id and device_authorization_endpoint, so the code path would only trigger for external IdPs (like Okta) that support it — but we haven't been able to test that end-to-end ourselves.

Our concern is that shipping this could create a confusing experience: if the auth code + PKCE flow fails for any reason on an instance where device flow isn't actually supported, the CLI would attempt device flow, get an error from the authorization server, and the user would see a failure message about a flow they never asked for. The fallback trigger is also quite broad — any tryAuthCodeLogin failure routes to device flow, including transient issues like network timeouts or the user closing their browser.

We're not closing this — the work is good and we want to land it. A few things that would help us get there:

  1. Narrowing the fallback trigger — only fall back to device flow when the auth code flow fails specifically because DCR/client registration is unavailable, not on any arbitrary failure
  2. Confirmation that you've tested this against an actual IdP — your PR description mentions Okta Security, so it sounds like you have. Any details on the end-to-end flow would be great
  3. Timing — we're actively working on auth improvements (PRs fix: persist oauth host without keychain prompts #68, fix: normalize host in resolveHost to prevent token lookup mismatch #72) and want to make sure everything composes cleanly

Thanks again for the contribution — this is exactly the kind of thing we'll need as more customers use external IdPs.

@steve-calvert-glean steve-calvert-glean added the enhancement New feature or request label Apr 4, 2026
When DCR is unavailable (e.g. Okta SSO), auth login now falls back to
the OAuth 2.0 Device Authorization Grant. The user approves login on a
verification page instead of a local redirect.
The previous fallback triggered on any tryAuthCodeLogin failure, including
transient issues like network timeouts or the user closing their browser.
Now device flow only activates when dcrOrStaticClient returns
errNoOAuthClient (no registration endpoint + no static client), not when
DCR was attempted and failed.

Made-with: Cursor
@pavlo-v-chernykh pavlo-v-chernykh force-pushed the feature/device-authorization-flow branch from 65ac121 to fb5d72c Compare April 4, 2026 22:02
@pavlo-v-chernykh
Copy link
Copy Markdown
Author

Thanks for the review, Steve.

1. Narrowed fallback trigger — introduced errNoOAuthClient sentinel in dcrOrStaticClient. Device flow only activates when the server has no registration endpoint and no static client is configured. DCR failures (403, 5xx, network) surface directly — no silent switch to device flow.

2. Testing — tested against a real Okta tenant with device flow enabled. Full flow works end-to-end: device code request, verification URL, user approval, token polling.

3. Timing — rebased onto latest main (includes #68 and #72). No conflicts, tests pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants