feat: add Device Authorization Grant (RFC 8628) as login fallback#60
Conversation
|
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 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 We're not closing this — the work is good and we want to land it. A few things that would help us get there:
Thanks again for the contribution — this is exactly the kind of thing we'll need as more customers use external IdPs. |
65ac121 to
fb5d72c
Compare
|
Thanks for the review, Steve. 1. Narrowed fallback trigger — introduced 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. |
fb5d72c to
0478ef9
Compare
|
@pavlo-v-chernykh I accidentally made a conflict for you (in #82), sorry about that |
0478ef9 to
774f1b6
Compare
|
@rwjblue-glean No worries, already rebased and resolved it! Let me know if there's anything else needed from my side to get this merged. |
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
…est helper PR gleanwork#79 removed the package-level discoveryHTTPClient var from discovery.go and inlined httputil.NewHTTPClient at each call site. The device.go file (added in a parallel branch) still referenced the deleted var, causing a build failure after rebase. Inline the client at both device.go call sites to match the rest of the auth package, and remove the now-unnecessary overrideDiscoveryHTTPClient helper and all 16 calls across test files (httptest.NewServer creates a real TCP server reachable by any client).
- Add auth:device debug namespace for tracing device flow login - Improve fallback message: "Your SSO provider requires device-based login" instead of confusing OAuth jargon - Rewrite README auth section with scannable table showing three login methods and when each is used - Add "Credential resolution order" subsection - Note that API tokens are scoped to individual user accounts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
774f1b6 to
2dee73a
Compare
|
Thanks again for this contribution. @pavlo-v-chernykh! It's released in v0.13.0. |
Summary
glean_device_flow_client_idanddevice_authorization_endpointfrom Glean's protected resource metadata and OIDC/RFC 8414 discoveryChanges
internal/auth/auth.go— refactoredLogin()intotryAuthCodeLogin+ device flow fallback chain; extractedsaveAndPrintTokenhelper that persists both tokens and client credentials for refreshinternal/auth/discovery.go— addedglean_device_flow_client_idto protected resource metadatainternal/auth/device.go— new file implementing RFC 8628: device code request, token polling withslow_downinterval 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 cancellationinternal/auth/discovery_test.go— added test forglean_device_flow_client_idparsingREADME.md+snippets/readme/snippet-04.sh— updated auth docs to mention device flowTest plan
go test -race ./...passesgolangci-lint runreports 0 issuesmarkdown-code checkconfirms docs in sync