Skip to content

fix(seo): request webmasters scope when minting ADC tokens - #109

Open
thelettere wants to merge 1 commit into
nowork-studio:mainfrom
thelettere:fix/gsc-adc-explicit-scopes
Open

fix(seo): request webmasters scope when minting ADC tokens#109
thelettere wants to merge 1 commit into
nowork-studio:mainfrom
thelettere:fix/gsc-adc-explicit-scopes

Conversation

@thelettere

Copy link
Copy Markdown

Problem

The SEO scripts mint a Google ADC access token by shelling out to:

["gcloud", "auth", "application-default", "print-access-token"]

with no --scopes argument, in four places — analyze_gsc.py, list_gsc_sites.py, url_inspection.py, preflight.py.

With user ADC this works, because the token silently inherits whatever scopes were stored at gcloud auth application-default login.

With service-account ADC (GOOGLE_APPLICATION_CREDENTIALS) it does not. gcloud mints a cloud-platform-only token, and every Search Console call fails:

403 { "message": "Request had insufficient authentication scopes.",
      "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT" }

That makes the SEO skills unusable from any unattended or headless context. This matters because a service account is often the only workable credential there — Workspace orgs can enforce Cloud session-control policies that force-expire any credential built on a human's Google session, regardless of how recently it was refreshed, and a headless run has nobody present to complete the reauth prompt.

Fix

Adds adc_access_token() to _gcloud.py. It requests webmasters.readonly,cloud-platform explicitly, and falls back to an unscoped request when the credential cannot mint those scopes — so a user ADC that was not granted them at login behaves exactly as it does today. The four scripts call it instead of shelling out individually.

The fallback is what makes this safe: it repairs the service-account path without changing the user-ADC path.

Verification

Both credential types, against a real Search Console property:

Path Before After
Service account (GOOGLE_APPLICATION_CREDENTIALS set) 403 ACCESS_TOKEN_SCOPE_INSUFFICIENT Summary: 5 clicks | 514 impressions | CTR 0.97% | Avg position 33.5
User ADC without those scopes granted "Could not get access token. Run: gcloud auth…" identical message, no regression

Also ruled out as alternatives, in case they come up in review: the CLOUDSDK_AUTH_SCOPES environment variable has no effect on ADC token minting, and gcloud config set auth/scopes errors with Section [auth] has no property [scopes]. A code change is the only route.

🤖 Generated with Claude Code

The SEO scripts shell out to `gcloud auth application-default
print-access-token` with no `--scopes` argument. With user ADC that
silently inherits whatever scopes were stored at login, so it works.

With service-account ADC (GOOGLE_APPLICATION_CREDENTIALS) it does not:
gcloud mints a cloud-platform-only token and every Search Console call
fails with 403 ACCESS_TOKEN_SCOPE_INSUFFICIENT. That makes the scripts
unusable from any unattended/headless context, where a service account
is the only credential type that isn't subject to interactive reauth
policies.

Add `adc_access_token()` to _gcloud.py. It requests
webmasters.readonly,cloud-platform explicitly, and falls back to an
unscoped request when the credential can't mint those scopes — so user
ADC that wasn't granted them at login keeps working exactly as before.

Verified both paths:
- service account: analyze_gsc.py returns data (was 403)
- user ADC without the scopes granted: unchanged failure message

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant