Our OAuth refresh tokens are being revoked every 2-4 days in a fully verified Production app. We have systematically ruled out every documented cause and are stuck.
SETUP:
- Project: publishbot-(PII Removed by Staff) (no organization)
- Publishing status: In production
- Branding: verified. Data access: verified (confirmed in Verification Center)
- Authorizing account: a standard @albarqsalh70 account
- Two separate Desktop OAuth clients (one for YouTube Data API v3 with youtube.upload + youtube.readonly, one for Business Profile API with business.manage)
- A separate Web OAuth client for our web app (tokens stored per-user in our DB)
SYMPTOM:
Every 2-4 days, refreshing returns: {“error”: “invalid_grant”, “error_description”: “Token has been expired or revoked.”}
This affects BOTH the Desktop clients (CLI) AND the Web client (web app) simultaneously — even though they are different client IDs with separately issued tokens. Re-authorizing fixes it for 2-4 days, then it happens again.
WHAT WE HAVE ALREADY RULED OUT:
- Testing mode — app is In production + verified (7-day rule does not apply).
- Old credentials created during Testing — we created brand new OAuth clients on July 10 while already in Production, issued fresh tokens. They were revoked again within 3 days.
- Token rotation — we verified the refresh_token value is unchanged after each refresh (no silent rotation, nothing to re-store).
- 50-token limit — we re-authorize manually only a few times, nowhere near the limit.
- Concurrent refresh / race conditions — we publish once per day; refreshes never overlap in time.
- 6-month inactivity — tokens are used daily.
- User revocation / password change — neither happened.
DIAGNOSTICS:
The raw token endpoint response contains only “error” and “error_description”. There is NO “error_subtype” field, so we cannot distinguish a genuine revocation from a session-control policy (e.g. invalid_rapt).
QUESTIONS:
- What could cause refresh tokens to be revoked every 2-4 days in a verified Production app?
- Why would tokens from two different OAuth clients (Desktop and Web) under the same Google account be revoked at the same time? This suggests something at the account or project level rather than the client level.
- How can we obtain the actual revocation reason when the token endpoint returns no “error_subtype”?
- Is there any configuration that makes these refresh tokens stable/long-lived?
This is blocking a production SaaS product — end users cannot reliably publish. Any guidance would be greatly appreciated.