Skip to content

fix(auth): retry stale scoped token once after 403#890

Open
clawsweeper[bot] wants to merge 1 commit into
mainfrom
clawsweeper/issue-openclaw-gogcli-889
Open

fix(auth): retry stale scoped token once after 403#890
clawsweeper[bot] wants to merge 1 commit into
mainfrom
clawsweeper/issue-openclaw-gogcli-889

Conversation

@clawsweeper

@clawsweeper clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a stored-OAuth-only retry for replayable Google 403 responses that indicate insufficient authentication scopes
  • force a fresh access-token mint or cached-token bypass before the single retry
  • preserve ordinary 403 behavior for true permission denials, Workspace policy failures, direct access tokens, service accounts, ADC, and non-replayable request bodies

Testing

  • go test -vet=off ./internal/googleapi
  • make ci

Fixes #889

@clawsweeper clawsweeper Bot added clawsweeper Tracked by ClawSweeper automation clawsweeper:autogenerated PR created automatically by ClawSweeper clawsweeper:autofix Bounded ClawSweeper-reviewed autofix without merge labels Jun 30, 2026
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Codex review: needs maintainer review before merge. Reviewed June 30, 2026, 1:48 AM ET / 05:48 UTC.

Summary
The PR adds a stored-OAuth-only auth refresh hook that retries one replayable Google 403 insufficient-scope response after forcing a fresh scoped access-token mint, with transport regression tests.

Reproducibility: no. live high-confidence reproduction was established in this review. Source inspection does show current main would return the first replayable 403 insufficient-scope response without refreshing, and the PR adds a focused test harness for that path.

Review metrics: 2 noteworthy metrics.

  • Files Touched: 3 implementation files, 1 test file. The PR reaches auth client setup, token persistence, and shared retry transport behavior.
  • Retry Budget Changed: 1 new 403 auth retry class. A previously terminal 4xx response can now trigger one additional request when the body matches insufficient-scope text.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #889
Summary: This PR is the implementation candidate for the linked open auth-provider issue about intermittent scoped-token 403s.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🌊 off-meta tidepool
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Let CI finish, then consider a redacted stored-OAuth Calendar or Contacts smoke before merge.

Risk before merge

  • [P1] The patch changes stored OAuth token-source caching, forced remint, and token metadata persistence; unit tests cannot fully prove live Google scoped-token propagation behavior.
  • [P1] If Google uses an insufficient-scope phrase for a true unrecoverable authorization problem, users may see one extra token refresh attempt or a refresh error before the final authorization failure.

Maintainer options:

  1. Validate OAuth Remint Before Merge (recommended)
    Wait for CI and, if credentials are available, run a redacted stored-OAuth Calendar or Contacts smoke that exercises the refreshed-token path before landing.
  2. Accept Unit-Tested Retry Scope
    Maintainers may merge with the added unit coverage only, accepting that the intermittent live Google behavior cannot be deterministically reproduced in CI.

Next step before merge

  • [P2] No narrow repair task is identified; the remaining action is maintainer and CI validation of the auth-provider retry behavior before merge.

Security
Cleared: No concrete security or supply-chain regression was found; the diff does not add dependencies, broaden secret exposure, or log token material.

Review details

Best possible solution:

Land the focused auth retry after CI and, ideally, a redacted stored-OAuth Calendar or Contacts smoke confirms the remint path without changing true permission-denial behavior.

Do we have a high-confidence way to reproduce the issue?

No live high-confidence reproduction was established in this review. Source inspection does show current main would return the first replayable 403 insufficient-scope response without refreshing, and the PR adds a focused test harness for that path.

Is this the best way to solve the issue?

Yes, the proposed one-time refresh/remint retry for replayable insufficient-scope 403s is the narrow maintainable direction. It should stay limited to stored OAuth and continue preserving direct access token, service account, ADC, ordinary 403, and non-replayable behavior.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 213ddb60d7d1.

Label changes

Label changes:

  • add P2: This is a normal auth-provider reliability fix for existing Calendar and Contacts workflows with limited blast radius.
  • add merge-risk: 🚨 auth-provider: The diff changes stored OAuth token refresh/remint behavior and token persistence, which CI cannot fully prove against live Google auth semantics.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This is a ClawSweeper bot PR, so the external-contributor real behavior proof gate does not apply; the PR body lists tests but no live OAuth proof.

Label justifications:

  • P2: This is a normal auth-provider reliability fix for existing Calendar and Contacts workflows with limited blast radius.
  • merge-risk: 🚨 auth-provider: The diff changes stored OAuth token refresh/remint behavior and token persistence, which CI cannot fully prove against live Google auth semantics.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This is a ClawSweeper bot PR, so the external-contributor real behavior proof gate does not apply; the PR body lists tests but no live OAuth proof.
Evidence reviewed

What I checked:

  • Repository policy read: AGENTS.md was read fully; its PR review guidance was applied by using gh PR inspection without switching branches or mutating the checkout. (AGENTS.md:1, 213ddb60d7d1)
  • Current main does not retry these 403s: On current main, RetryTransport retries 429 and 5xx, then returns other 4xx responses without an auth refresh/retry path. (internal/googleapi/transport.go:137, 213ddb60d7d1)
  • PR wires auth refresh only when supported: The PR wraps the OAuth transport in RetryTransport and assigns RefreshAuth only when the selected token source exposes ForceRefresh(context.Context) error. (internal/googleapi/client.go:154, fb5d8f56058f)
  • PR bypasses cached scoped token on refresh: The PR adds resettableOAuthTokenSource and persistingTokenSource.ForceRefresh so the retry path replaces the cached OAuth token source, mints a fresh token, and persists returned token metadata. (internal/googleapi/client_auth.go:81, fb5d8f56058f)
  • PR adds one guarded 403 retry: The transport retries only one 403 whose response body indicates insufficient scopes, only when RefreshAuth is configured and the request is replayable. (internal/googleapi/transport.go:143, fb5d8f56058f)
  • Targeted regression coverage exists: The PR adds tests for refreshing once on an insufficient-scope 403, preserving ordinary 403 behavior, and avoiding retries for non-replayable request bodies. (internal/googleapi/transport_more_test.go:226, fb5d8f56058f)

Likely related people:

  • steipete: Recent history for the scoped OAuth/token metadata path and authenticated client setup is dominated by steipete-authored or steipete-merged work, including observed OAuth scope reconciliation and auth dependency injection. (role: recent auth and Google API area contributor; confidence: high; commits: 6bd333a1e141, 05b75b44cd41, 4cac149d75a7; files: internal/googleapi/client_auth.go, internal/googleapi/client.go)
  • salmonumbrella: The retry transport behavior being extended by this PR traces back to salmonumbrella's original RetryTransport implementation for 429 and 5xx handling. (role: retry transport introducer; confidence: medium; commits: d2be673d1004; files: internal/googleapi/transport.go)
  • tengis617: The ADC auth path in the same client setup was introduced through tengis617's PR; this PR intentionally avoids changing ADC behavior, making them an adjacent routing candidate rather than the primary owner. (role: adjacent auth-mode contributor; confidence: low; commits: 45c272ffe8a2; files: internal/googleapi/client.go)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. clawsweeper:human-review ClawSweeper automerge is paused for maintainer review labels Jun 30, 2026
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

🦞✅
ClawSweeper is pausing this repair loop for human review.

Source: clawsweeper[bot]
Reason: - [P2] No narrow repair task is identified; the remaining action is maintainer and CI validation of the auth-provider retry behavior before merge.; Cleared: No concrete security or supply-chain regression was found; the diff does not add dependencies, broaden secret exposure, or log token material. (sha=fb5d8f56058f750f8a81940a9435b927ca8e2c73)

Why human review is needed:
This item has security-sensitive risk. ClawSweeper is pausing instead of making an autonomous change that could affect trust, credentials, permissions, or exposure.

What the maintainer can do as a next step:
If the maintainer accepts the current risk and wants ClawSweeper to continue merge gates, comment @clawsweeper approve. If the security-sensitive detail still needs changes, describe the safe path or push the fix, then comment @clawsweeper automerge. If the risk should not be automated, keep the PR paused for manual review or comment @clawsweeper stop.

I added clawsweeper:human-review and left the final call with a maintainer.

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

Labels

clawsweeper:autofix Bounded ClawSweeper-reviewed autofix without merge clawsweeper:autogenerated PR created automatically by ClawSweeper clawsweeper:human-review ClawSweeper automerge is paused for maintainer review clawsweeper Tracked by ClawSweeper automation merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intermittent 403 'insufficient scopes' that succeeds on retry with same token (per-call scope mint?)

0 participants