gws auth login can silently leave a stale/split token cache, causing 403 insufficient authentication scopes after re-auth
Summary
After re-authenticating (gws auth login -s drive,docs), gws continued returning 403 insufficient authentication scopes on every Drive API call, while Gmail-scoped calls succeeded fine throughout. The login command's own output correctly listed https://www.googleapis.com/auth/drive as a granted scope, and ~/.config/gws/credentials.enc had a fresh timestamp — but the actual Drive API calls kept failing as if that scope had never been granted.
Environment
gwsversion: 0.11.1 (@googleworkspace/cli)- macOS 15.7.3 (Build 24G419)
- Auth method: OAuth2, installed/desktop client (
redirect_uris: ["http://localhost"]) - Keyring backend:
keyring
What was ruled out before finding the real cause
Extensive troubleshooting confirmed this was not caused by any of the following (each checked directly):
- OAuth consent screen scope configuration (Drive API confirmed
ENABLEDviagcloud services list) - OAuth consent screen test users list (account confirmed present)
- A stray local process holding a port from a previous
gws auth logininvocation (found and killed one, no change) - A full OS reboot (no change — rules out any in-memory/process-level caching)
client_secret.jsonvalidity (if this were invalid, login itself would fail withinvalid_client, not succeed and then fail on API calls — and other-scoped calls, e.g. Gmail, worked fine throughout)
Multiple full gws auth login -s drive,docs re-runs across this window, including after switching to a different Google account and back, did not resolve the issue.
Root cause (as best diagnosed)
~/.config/gws/ contains two separate local token/credential stores:
credentials.enc(encrypted, gets a fresh timestamp on everygws auth login)token_cache.json(binary — not actually JSON despite the extension/name; failed UTF-8 decode when inspected)
A normal gws auth login re-auth appears to refresh credentials.enc but not fully invalidate/replace whatever state token_cache.json holds (or vice versa — the exact read/write interaction between the two wasn't fully traced from the outside). The practical symptom: the CLI looks like it completed a fresh login with the requested scope, but the token actually used for API calls doesn't carry that scope.
Workaround that fixed it
Manually deleting the cached credential/token state (while preserving the app config) and then doing a completely fresh login resolved the issue immediately:
rm ~/.config/gws/credentials.enc ~/.config/gws/token_cache.json
rm -rf ~/.config/gws/cache/* # cached API discovery docs, unrelated to auth but safe to clear too
gws auth login -s drive,docs(client_secret.json and .encryption_key were left untouched — those are the app identity/encryption key, not per-session state.)
Immediately after this, gws drive files list succeeded and returned real results.
Suggested fix
gws auth login (or a new --fresh/--clear-cache flag) should fully clear all local token/credential state before starting a new interactive login, rather than leaving a possibly-stale secondary cache (token_cache.json) in place alongside a freshly-written credentials.enc. Right now the only way to force a truly clean re-auth is to know to manually delete files inside ~/.config/gws/ — there's no documented or CLI-exposed way to do this.
Happy to provide more detail if useful — this took a couple hours of systematic elimination to track down, so hopefully this saves someone else the trouble.
Source: googleworkspace/cli