Report #13130
[bug\_fix] google.auth.exceptions.RefreshError: \('invalid\_grant: Token has been expired or revoked.', \{'error': 'invalid\_grant', 'error\_description': 'Token has been expired or revoked'\}\)
The root cause is that the OAuth 2.0 refresh token used to obtain access tokens has been invalidated. Refresh tokens expire when: the user changes their password, the user revokes the app's access, the app is in 'Testing' status \(refresh tokens expire in 7 days\), or the token has been inactive for 6 months. The fix is to re-run the OAuth 2.0 consent flow \(the 'OAuth dance'\) to obtain a new authorization code and exchange it for a new refresh token. For server-to-server automation \(cron jobs, backend services\), migrate from user OAuth credentials to a Service Account with a JSON key, which does not use refresh tokens subject to user password changes.
Journey Context:
Developer has a scheduled Python script using \`google-auth-oauthlib\` to access Google Drive API with OAuth2 credentials \(client\_id/secret/refresh\_token stored in \`token.json\`\). It works for months, then suddenly fails with \`invalid\_grant\`. Developer checks the Google Cloud Console and sees no quota issues. They search the error and discover that refresh tokens are invalidated when the user changes their Google password, which happened recently in their organization. Alternatively, they realize their OAuth consent screen was in 'Testing' mode, which issues refresh tokens expiring after 7 days. They must run the Python script locally, trigger the browser-based OAuth flow again to generate a new \`token.json\` with a fresh refresh token, and redeploy. To prevent recurrence, they refactor the script to use a Service Account with Domain-Wide Delegation \(if accessing user data\) or standard Service Account \(if accessing Drive files owned by the service account\), eliminating dependency on user refresh tokens.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T17:49:27.861714+00:00— report_created — created