feat(auth): recover revoked OAuth tokens safely - #974
Conversation
…ant) When the stored OAuth refresh token is expired or revoked (invalid_grant), gog currently fails with a hard error and requires the user to manually re-run 'gog auth add'. This is in contrast to other CLI tools (e.g. Rust's yup-oauth2 InstalledFlowAuthenticator) which automatically fall back to a browser-based re-authorization flow when the refresh token is invalid. This PR adds auto-reauth support: - In interactive sessions (TTY stdin, --no-input not set), gog detects invalid_grant during token refresh, launches a browser-based OAuth flow (with --force-consent to ensure a new refresh token), persists it to the keyring, resets the in-memory token source, and retries the original API request. - In non-interactive sessions (--no-input or non-TTY stdin), gog surfaces a clear error message with the manual 'gog auth add' command instead. - Excluded for ADC, service accounts, and direct access tokens. - The reauth preserves the stored token's full scope/service set, preventing silent grant narrowing. - The authorized email is verified to match the expected account before persisting. - The in-memory token source (resettableOAuthTokenSource) is rebuilt with the new refresh token so the retried request doesn't reuse the revoked token. Design inspired by yup-oauth2's InstalledFlowAuthenticator.find_token_info() fallback pattern: https://github.com/dermesser/yup-oauth2/blob/master/src/authenticator.rs Co-authored-by: Yasuhiro Inami <inamiy@gmail.com>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 9, 2026, 10:08 PM ET / August 10, 2026, 02:08 UTC. ClawSweeper reviewWhat this changesAdds an explicitly confirmed browser re-authorization fallback for revoked stored OAuth refresh tokens, plus small dependency and CI pin updates. Merge readinessKeep open. This is a clean, maintainer-authored landing branch for the revoked-token recovery feature; current main does not implement that recovery path, and the patch preserves explicit-consent and non-interactive safeguards. Priority: P2 Review scores
Verification
How this fits togethergog uses stored OAuth credentials to obtain access tokens before Google API requests reach each service client. On a typed revoked-token failure, this path can now ask an interactive user to re-authorize, store the replacement token, and retry the original request. flowchart LR
A[CLI command] --> B[Stored OAuth token]
B --> C[Google token refresh]
C --> D{Revoked token?}
D -->|no| E[Google API request]
D -->|interactive| F[Confirm re-authorization]
F --> G[Persist replacement token]
G --> E
D -->|non-interactive| H[Manual recovery guidance]
Before merge
Agent review detailsSecurityNone. Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Retain the typed-error-only, explicitly confirmed recovery design with stored-token scope preservation and identity validation, then land it through the normal maintainer review path. Do we have a high-confidence way to reproduce the issue? Not applicable as an issue report. The PR supplies a concrete disposable-token validation path and source-backed tests for the recovery and suppression boundaries. Is this the best way to solve the issue? Yes. It extends the existing OAuth authorization flow only after a typed revoked-token error and explicit confirmation, while keeping ADC, service-account, direct-token, non-interactive, and non-replayable paths out of the fallback. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e4e71c68224a. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
Summary
Maintainer landing branch for #973. This preserves @inamiy's authored feature commit, then hardens the released auth path before landing:
invalid_grantfailures only;RefreshToken;--no-input, non-TTY, ADC, service-account, direct-token, non-replayable request, and single-retry boundaries intact.Also includes the required dependency pass: Kong 1.16.1, Cloudflare Workers types 5.20260809.1, and pnpm 11.21.0.
Proof
make cigo test -race ./internal/googleapi/... -run Reauth -count=1wrangler deploy --dry-run--no-input: exit 1, no prompt,invalid_grant, actionablegog auth addhintn: explicit account-scoped confirmation, exit 1, no OAuth URL or credential outputThe contributor's live Google proof covers successful browser consent, token persistence, request replay, and non-interactive suppression: #973 (comment)
No release is included.