Skip to content

fix(auth): persist rotated refresh tokens during API calls#373

Merged
steipete merged 1 commit intoopenclaw:mainfrom
joshp123:fix/persist-rotated-refresh-token
Mar 7, 2026
Merged

fix(auth): persist rotated refresh tokens during API calls#373
steipete merged 1 commit intoopenclaw:mainfrom
joshp123:fix/persist-rotated-refresh-token

Conversation

@joshp123
Copy link
Copy Markdown
Contributor

Summary

Persist rotated refresh tokens returned by Google during normal API token refreshes.

Why

gogcli currently loads refresh tokens from keyring and uses oauth2.TokenSource, but runtime API flows do not write back a rotated refresh token. In multi-process usage this can leave keyring state stale across invocations.

What changed

  • add persistingTokenSource wrapper in internal/googleapi/client.go
  • wrap the existing oauth2 token source in tokenSourceForAccountScopes
  • when Token() returns a different refresh token, persist it with store.SetToken(...)
  • keep persist failures non-fatal (warn + continue)
  • add unit tests in internal/googleapi/client_more_test.go for:
    • rotated token persists
    • unchanged token does not persist
    • persist failure is non-fatal

Validation

  • go test ./internal/googleapi

Why
- gogcli refreshed access tokens from a stored refresh token but never wrote back
  a rotated refresh token returned by Google.
- In multi-process CLI usage this can leave keyring state stale across invocations
  and eventually cause invalid_grant when the old token is retired.

What
- add persistingTokenSource wrapper in internal/googleapi/client.go
- wrap oauth2.Config TokenSource in tokenSourceForAccountScopes
- persist rotated refresh token back into secrets store when it changes
- keep persistence failures non-fatal (warn, return token)
- add unit tests for rotate/no-rotate/persist-failure paths

Tests
- go test ./internal/googleapi
@steipete steipete merged commit 59ab294 into openclaw:main Mar 7, 2026
1 check passed
@steipete
Copy link
Copy Markdown
Collaborator

steipete commented Mar 7, 2026

Follow-up landed on main after the merge race:

  • Gate: make fmt && make lint && make test && make ci
  • Fixup land commit: pending
  • PR merge commit: 59ab294

Thanks @joshp123!

@steipete
Copy link
Copy Markdown
Collaborator

steipete commented Mar 7, 2026

Final follow-up SHA:

klodr pushed a commit to klodr/gogcli that referenced this pull request Apr 22, 2026
)

Why
- gogcli refreshed access tokens from a stored refresh token but never wrote back
  a rotated refresh token returned by Google.
- In multi-process CLI usage this can leave keyring state stale across invocations
  and eventually cause invalid_grant when the old token is retired.

What
- add persistingTokenSource wrapper in internal/googleapi/client.go
- wrap oauth2.Config TokenSource in tokenSourceForAccountScopes
- persist rotated refresh token back into secrets store when it changes
- keep persistence failures non-fatal (warn, return token)
- add unit tests for rotate/no-rotate/persist-failure paths

Tests
- go test ./internal/googleapi
klodr pushed a commit to klodr/gogcli that referenced this pull request Apr 22, 2026
Sign up for free to 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.

2 participants