Publish Google Cloud OAuth app to eliminate 7-day token expiry and 1-hour access token limit #261

Closed
opened 2026-04-04 15:36:23 +00:00 by forgejo_admin · 0 comments
Contributor

Type

Bug

Lineage

Standalone — recurring blocker across every session that uses Gmail. Token expired 5 times in the 2026-04-03/04 session alone, blocking email sends each time.

Repo

forgejo_admin/pal-e-platform (platform-level, affects all services using Gmail OAuth)

What Broke

Gmail OAuth tokens expire every hour (access token) and every 7 days (refresh token) because the Google Cloud OAuth app is in Testing mode. This forces manual re-auth via browser every time the token expires, blocking all email operations.

Impact:

  • Every Claude session that sends email hits this wall
  • basketball-api email endpoints can't be tested programmatically
  • Gmail MCP tools die mid-session
  • The gmail-reauth.sh script and Prometheus alerts (6-day/7-day) are bandaids, not fixes

Root cause: Google Cloud project gmail-oauth-486921 has an unpublished OAuth consent screen. Google policy for unpublished/testing apps:

  • Access tokens: 1 hour lifetime, no auto-refresh after consent screen testing mode limits
  • Refresh tokens: 7-day lifetime (604799 seconds), then completely dead
  • refresh_token_expires_in: 604799 in the token file confirms Testing mode

Repro Steps

  1. Auth Gmail via MCP (gmail_reauth_start + gmail_reauth_complete)
  2. Send an email — works
  3. Wait 1 hour
  4. Try to send another email — 401 Unauthorized
  5. Must re-auth again

Expected Behavior

Auth once, tokens auto-refresh indefinitely. The gmail-sdk already has auto-refresh logic (auth.py:157-179) that works correctly when the refresh token is valid.

Environment

  • Google Cloud project: gmail-oauth-486921
  • OAuth client: 233869493443-e81l55kmgjm21jl7n8jm9pnjodgatv1a.apps.googleusercontent.com
  • Client type: Desktop/Installed (redirect_uri: http://localhost)
  • Gmail account: westsidebasktball@gmail.com (typo is real, missing 'e')
  • Token file: ~/secrets/google-oauth/gmail-westsidebasketball.json
  • MCP server: ~/gmail-mcp/ using gmail-sdk for token management
  • Consumers: Gmail MCP, basketball-api pod, westside-email service

File Targets

No code changes. This is a Google Cloud Console configuration change.

Steps:

  1. Go to Google Cloud Console → APIs & Services → OAuth consent screen (project: gmail-oauth-486921)
  2. Determine which Google account owns this project (unknown — need to check draneylucas, lucastoddraney, devopsphilosopher, westsidebasketball accounts)
  3. Fill in required fields for publishing: app name, support email, developer contact, privacy policy URL
  4. Click "Publish App"
  5. Re-auth one final time via gmail_reauth_start / gmail_reauth_complete
  6. Verify refresh_token_expires_in is no longer 604799 (7 days)

Post-publish:

  • ~/secrets/google-oauth/gmail-westsidebasketball.json — will contain long-lived refresh token
  • k8s secret gmail-oauth-westsidebasketball in basketball-api namespace — update from local
  • SOP note in pal-e-docs: document the fix and why it was needed

Acceptance Criteria

  • Google Cloud OAuth app published (out of Testing mode)
  • Fresh token obtained with long-lived refresh token
  • refresh_token_expires_in is NOT 604799 in the token file
  • Gmail MCP works for 24+ hours without re-auth
  • k8s secret updated with fresh token
  • SOP note sop-gmail-oauth created documenting the permanent fix
  • Prometheus alerts GmailOAuthTokenExpiringSoon / GmailOAuthTokenExpired stop firing

Test Expectations

  • Send email via Gmail MCP, wait 2 hours, send another — no 401
  • Verify auto-refresh works: gmail_get_profile succeeds after access token expiry without manual reauth

Constraints

  • Need to identify which Google account owns project gmail-oauth-486921
  • Publishing may require a privacy policy URL (can use the westside landing page)
  • Google may take up to 24 hours to process the publish request
  • No code changes in gmail-sdk, gmail-mcp, or basketball-api — the auto-refresh logic already works

Checklist

  • Project owner account identified
  • OAuth app published
  • Token refreshed and verified
  • k8s secrets updated
  • SOP written
  • pal-e-platform — project this affects
  • scripts/gmail-reauth.sh — current bandaid (PR #222)
  • terraform/modules/monitoring/main.tf — Prometheus alerts for token expiry
  • basketball-api#311, #312, #313 — email features blocked by this tonight
### Type Bug ### Lineage Standalone — recurring blocker across every session that uses Gmail. Token expired 5 times in the 2026-04-03/04 session alone, blocking email sends each time. ### Repo `forgejo_admin/pal-e-platform` (platform-level, affects all services using Gmail OAuth) ### What Broke Gmail OAuth tokens expire every hour (access token) and every 7 days (refresh token) because the Google Cloud OAuth app is in **Testing mode**. This forces manual re-auth via browser every time the token expires, blocking all email operations. **Impact:** - Every Claude session that sends email hits this wall - basketball-api email endpoints can't be tested programmatically - Gmail MCP tools die mid-session - The `gmail-reauth.sh` script and Prometheus alerts (6-day/7-day) are bandaids, not fixes **Root cause:** Google Cloud project `gmail-oauth-486921` has an unpublished OAuth consent screen. Google policy for unpublished/testing apps: - Access tokens: 1 hour lifetime, no auto-refresh after consent screen testing mode limits - Refresh tokens: 7-day lifetime (604799 seconds), then completely dead - `refresh_token_expires_in: 604799` in the token file confirms Testing mode ### Repro Steps 1. Auth Gmail via MCP (`gmail_reauth_start` + `gmail_reauth_complete`) 2. Send an email — works 3. Wait 1 hour 4. Try to send another email — 401 Unauthorized 5. Must re-auth again ### Expected Behavior Auth once, tokens auto-refresh indefinitely. The gmail-sdk already has auto-refresh logic (`auth.py:157-179`) that works correctly when the refresh token is valid. ### Environment - Google Cloud project: `gmail-oauth-486921` - OAuth client: `233869493443-e81l55kmgjm21jl7n8jm9pnjodgatv1a.apps.googleusercontent.com` - Client type: Desktop/Installed (redirect_uri: http://localhost) - Gmail account: westsidebasktball@gmail.com (typo is real, missing 'e') - Token file: `~/secrets/google-oauth/gmail-westsidebasketball.json` - MCP server: `~/gmail-mcp/` using `gmail-sdk` for token management - Consumers: Gmail MCP, basketball-api pod, westside-email service ### File Targets No code changes. This is a Google Cloud Console configuration change. Steps: 1. Go to Google Cloud Console → APIs & Services → OAuth consent screen (project: `gmail-oauth-486921`) 2. Determine which Google account owns this project (unknown — need to check draneylucas, lucastoddraney, devopsphilosopher, westsidebasketball accounts) 3. Fill in required fields for publishing: app name, support email, developer contact, privacy policy URL 4. Click "Publish App" 5. Re-auth one final time via `gmail_reauth_start` / `gmail_reauth_complete` 6. Verify `refresh_token_expires_in` is no longer 604799 (7 days) Post-publish: - `~/secrets/google-oauth/gmail-westsidebasketball.json` — will contain long-lived refresh token - k8s secret `gmail-oauth-westsidebasketball` in basketball-api namespace — update from local - SOP note in pal-e-docs: document the fix and why it was needed ### Acceptance Criteria - [ ] Google Cloud OAuth app published (out of Testing mode) - [ ] Fresh token obtained with long-lived refresh token - [ ] `refresh_token_expires_in` is NOT 604799 in the token file - [ ] Gmail MCP works for 24+ hours without re-auth - [ ] k8s secret updated with fresh token - [ ] SOP note `sop-gmail-oauth` created documenting the permanent fix - [ ] Prometheus alerts `GmailOAuthTokenExpiringSoon` / `GmailOAuthTokenExpired` stop firing ### Test Expectations - [ ] Send email via Gmail MCP, wait 2 hours, send another — no 401 - [ ] Verify auto-refresh works: `gmail_get_profile` succeeds after access token expiry without manual reauth ### Constraints - Need to identify which Google account owns project `gmail-oauth-486921` - Publishing may require a privacy policy URL (can use the westside landing page) - Google may take up to 24 hours to process the publish request - No code changes in gmail-sdk, gmail-mcp, or basketball-api — the auto-refresh logic already works ### Checklist - [ ] Project owner account identified - [ ] OAuth app published - [ ] Token refreshed and verified - [ ] k8s secrets updated - [ ] SOP written ### Related - `pal-e-platform` — project this affects - `scripts/gmail-reauth.sh` — current bandaid (PR #222) - `terraform/modules/monitoring/main.tf` — Prometheus alerts for token expiry - basketball-api#311, #312, #313 — email features blocked by this tonight
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/pal-e-platform#261
No description provided.