Summary
gog auth list reports the scope set stored at token-add time in the keyring entry, but a stored token will often successfully execute API calls against scopes it does not list. This caused a 30+ minute false-alarm investigation in one of our agent runs: auth list reported an account as calendar-only, yet gmail send on that same account succeeded.
Reproduction (locally observed)
$ gog --version
v0.12.0 (c18c58c 2026-03-09T05:53:14Z)
$ gog auth list
barry@willcurran.com default calendar 2026-02-26T18:45:40Z oauth
flash@willcurran.com default calendar,gmail 2026-04-15T22:01:53Z oauth
$ gog auth list --json
{
"accounts": [
{
"email": "barry@willcurran.com",
"services": ["calendar"],
"scopes": [
"email",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/userinfo.email",
"openid"
],
...
}
]
}
$ gog gmail --account barry@willcurran.com search "newer_than:1d" --results-only
ID DATE FROM SUBJECT LABELS THREAD
19e6a781e1d2bfff 2026-05-27 10:25 barry@curran.co Re: ... SENT [2 msgs]
$ gog --verbose gmail --account barry@willcurran.com search "newer_than:1d" --results-only 2>&1 | head -3
time=... level=DEBUG msg=\"creating client options with custom scopes\" serviceLabel=gmail email=barry@willcurran.com
time=... level=DEBUG msg=\"client options with custom scopes created successfully\" serviceLabel=gmail email=barry@willcurran.com
The keyring file's stored scope set does not include gmail, yet gmail send / gmail search both succeed against this account. (We confirmed actual send via msg-id 19e6a77240c18d79 — message landed in Sent.)
Root cause (hypothesis)
Google's OAuth server honors incremental authorization — if the user has previously consented to a wider scope set under the SAME OAuth client (across any account), Google will issue access tokens with the requested scopes off the refresh token even when that specific refresh token's original consent only covered a subset. gog's request-time path \"creating client options with custom scopes\" is asking for gmail scope and Google grants it; meanwhile the keyring entry's stored scope set is stale because it was never re-issued to reflect the broader consent.
Why this matters
Operators (and agents) trust gog auth list as the source of truth for "can this account do X?" When the displayed scope set is a strict subset of what actually works, they either:
(a) waste time re-authing accounts that don't need it, or
(b) raise false-alarm "auth blocker" notifications when there is no actual blocker.
Both happened in our system.
Suggested fix (one of)
- Detect + persist scope upgrades. When
gog successfully obtains an access token off a refresh token with a scope set that exceeds the stored consent set, write the new scope union back to the keyring entry so subsequent auth list calls reflect reality.
gog auth refresh <email> command. Trigger a refresh+token-exchange that updates the stored scope metadata without a full browser re-consent flow.
auth list warning glyph. When a stored token's scope set has been observed to be insufficient for a recent successful call, mark the row with a * and explain in auth list --help.
Option 1 is the most user-friendly (auto-heals). Option 2 is the smallest change. Option 3 is the cheapest but does not auto-heal.
Workaround
gog auth add <email> --services gmail,calendar --force-consent re-authorizes through the browser flow with the explicit superset, which refreshes the keyring entry's stored scope list. (Verified locally that this is the path that updates the metadata; running it for this account is a separate Will-side step requiring interactive browser action.)
Environment
- Version: v0.12.0 (c18c58c)
- Backend: file keyring (passwords managed in 1Password via gog-safe wrapper)
- macOS 25.2.0 (Darwin), arm64
- Latest release is v0.19.0; release notes since v0.12.0 do not appear to address this specifically ("auth list" changes since v0.12.0 are about graceful unreadable-entry handling and per-client filtering, not scope-upgrade reconciliation).
Happy to test a fix locally; the affected account is barry@willcurran.com (Workspace) on this machine.
Summary
gog auth listreports the scope set stored at token-add time in the keyring entry, but a stored token will often successfully execute API calls against scopes it does not list. This caused a 30+ minute false-alarm investigation in one of our agent runs:auth listreported an account ascalendar-only, yetgmail sendon that same account succeeded.Reproduction (locally observed)
The keyring file's stored scope set does not include gmail, yet
gmail send/gmail searchboth succeed against this account. (We confirmed actual send via msg-id19e6a77240c18d79— message landed in Sent.)Root cause (hypothesis)
Google's OAuth server honors incremental authorization — if the user has previously consented to a wider scope set under the SAME OAuth client (across any account), Google will issue access tokens with the requested scopes off the refresh token even when that specific refresh token's original consent only covered a subset. gog's request-time path
\"creating client options with custom scopes\"is asking for gmail scope and Google grants it; meanwhile the keyring entry's stored scope set is stale because it was never re-issued to reflect the broader consent.Why this matters
Operators (and agents) trust
gog auth listas the source of truth for "can this account do X?" When the displayed scope set is a strict subset of what actually works, they either:(a) waste time re-authing accounts that don't need it, or
(b) raise false-alarm "auth blocker" notifications when there is no actual blocker.
Both happened in our system.
Suggested fix (one of)
gogsuccessfully obtains an access token off a refresh token with a scope set that exceeds the stored consent set, write the new scope union back to the keyring entry so subsequentauth listcalls reflect reality.gog auth refresh <email>command. Trigger a refresh+token-exchange that updates the stored scope metadata without a full browser re-consent flow.auth listwarning glyph. When a stored token's scope set has been observed to be insufficient for a recent successful call, mark the row with a*and explain inauth list --help.Option 1 is the most user-friendly (auto-heals). Option 2 is the smallest change. Option 3 is the cheapest but does not auto-heal.
Workaround
gog auth add <email> --services gmail,calendar --force-consentre-authorizes through the browser flow with the explicit superset, which refreshes the keyring entry's stored scope list. (Verified locally that this is the path that updates the metadata; running it for this account is a separate Will-side step requiring interactive browser action.)Environment
Happy to test a fix locally; the affected account is barry@willcurran.com (Workspace) on this machine.