api
authentication
ai_generated
partial
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.',)
ID: api/google-oauth-refresh-token-revoked
70%Fix Rate
82%Confidence
3Evidence
2023-01-01First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| any | active | — | — | — |
Root Cause
Google silently revokes refresh tokens after 6 months of inactivity, when user changes password, or when >50 tokens exist per client. The 50-token limit is barely documented.
genericWorkarounds
-
85% success Store refresh tokens per-user and reuse existing ones via prompt=none
If user already has a refresh token in your DB, use it instead of initiating new OAuth flow
-
90% success Implement re-authentication flow that gracefully handles revocation
try: creds.refresh(request) except RefreshError: redirect_to_oauth_consent()
-
88% success Use service accounts for server-to-server auth instead of user OAuth
creds = service_account.Credentials.from_service_account_file('key.json', scopes=SCOPES)
Dead Ends
Common approaches that don't work:
-
Store and reuse the refresh token indefinitely
88% fail
Google has a hidden 50 refresh token limit per user per OAuth client. Token 51 silently invalidates token 1. Also, 6 months inactivity = revocation.
-
Request a new refresh token on every auth flow
75% fail
Each new token pushes out the oldest. If user has multiple devices, they kick each other out.