Skip to content

Recover Google sessions with silent Gmail token refresh - #40

Open
bcbetterninja wants to merge 1 commit into
masterfrom
fix/google-session-refresh
Open

bcbetterninja wants to merge 1 commit into
masterfrom
fix/google-session-refresh

Conversation

@bcbetterninja

@bcbetterninja bcbetterninja commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Gmail requests previously surfaced an authentication error when Google rejected an access token that still appeared valid locally. Refresh failures also told users to reauthenticate for any HTTP 400/401, including OAuth client configuration problems.

Retry a Gmail request once after an explicit 401 using a silently refreshed token. Concurrent rejected requests reuse the new saved token, replacement refresh tokens are persisted, and only an invalid refresh grant prompts reauthentication. Permission and service errors are not retried. Document Google's seven-day refresh-token limit for external OAuth apps in Testing; BetterMail's actual OAuth publishing status remains unverified.

Validation: solution build passes with no warnings or errors; all 674 tests pass against current master, including the merged Tunnels/Web changes. The 13 new authentication regression cases cover cached and rotated tokens, OAuth error classification, replayed request bodies, bounded retries, and concurrent 401 recovery. Seven cases reproduced failures before the fix.

This PR covers Google authentication reliability. Gmail push delivery still requires Cloud Pub/Sub provisioning and authenticated routing; it is not enabled by this change. No live-account or cloud configuration changes were made.

Summary by CodeRabbit

  • Improvements
    • Google sign-in now refreshes expired or rejected access tokens automatically and retries a Gmail request once after an authorization failure.
    • Concurrent requests share a token refresh, and replacement refresh tokens are retained when provided.
    • Authentication errors are handled more clearly: some require signing in again, while configuration and temporary service errors do not.
  • Documentation
    • Added guidance on refresh-token expiry, invalidation and Google production-app requirements.

@bcbetterninja

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T00:30:47.588746Z 438a7b4 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 99edfdf5-d348-4ad5-bf68-e25bb1312fbd
📥 Commits

Reviewing files that changed from the base of the PR and between 917fd18 and 438a7b4.

📒 Files selected for processing: 4
  • README.md
  • src/BetterMail.Google/GoogleAuthService.cs
  • src/BetterMail.Google/GoogleGmailProvider.cs
  • tests/BetterMail.Tests/GoogleAuthTests.cs

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.

Walkthrough

Google authentication now shares access-token refresh logic and classifies OAuth errors. Gmail requests retry once after a 401. Tests cover token reuse, refresh, error handling, retry limits and concurrent requests. The README documents these behaviours and refresh-token expiry guidance.

Changes

Google authentication and Gmail requests

Layer / File(s) Summary
Shared token refresh and OAuth error handling
src/BetterMail.Google/GoogleAuthService.cs, tests/BetterMail.Tests/GoogleAuthTests.cs, README.md
Token reuse and refresh now follow shared rules. Replacement refresh tokens are retained when provided. OAuth errors receive distinct handling. Tests and README updates cover these changes and refresh-token invalidation guidance.
Gmail 401 retry and concurrent refresh
src/BetterMail.Google/GoogleGmailProvider.cs, tests/BetterMail.Tests/GoogleAuthTests.cs
Gmail requests retry once after a 401. Tests cover retry behaviour, non-401 failures, and concurrent requests sharing a refresh.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant GoogleGmailProvider
  participant GoogleAuthService
  participant GmailAPI
  participant GoogleOAuthEndpoint
  participant TokenStore
  GoogleGmailProvider->>GoogleAuthService: Get access token
  GoogleGmailProvider->>GmailAPI: Send request with access token
  GmailAPI-->>GoogleGmailProvider: Return 401
  GoogleGmailProvider->>GoogleAuthService: Refresh rejected access token
  GoogleAuthService->>GoogleOAuthEndpoint: Submit refresh token
  GoogleOAuthEndpoint-->>GoogleAuthService: Return replacement access token
  GoogleAuthService->>TokenStore: Save refreshed token
  GoogleGmailProvider->>GmailAPI: Retry request once
Loading

Suggested reviewers: mrinc

Merge Risk: ⚪ Minimal · up to 438a7

The Gmail retry can resend its request body after a 401. No merge-blocking issue remains identified; normal checks can proceed.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 3 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: silent Gmail token refresh to recover Google sessions.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 3 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit watched the tokens renew,
Then saw one retry go through.
The refresh stayed shared,
The old token was spared,
And the Gmail requests hopped anew.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 438a7b4600

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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.

1 participant