auth: bring-your-own Google OAuth client (no app verification needed)#1
Open
GazingInSpring wants to merge 1 commit into
Open
auth: bring-your-own Google OAuth client (no app verification needed)#1GazingInSpring wants to merge 1 commit into
GazingInSpring wants to merge 1 commit into
Conversation
gmail.readonly is a Google restricted scope, so a single shared ZeroEntropy OAuth app would need a CASA security audit before external users could authorize without warnings. Instead, each user now supplies their own Google Cloud OAuth client credentials, so authorization runs against a Google project they control — self-use needs no Google verification. - Remove the hardcoded shared client_id/client_secret from gmail_client.py. - config.get_google_client_config resolves BYO credentials, mirroring how the ZeroEntropy API key is handled: env vars (ZEMAIL_GOOGLE_CLIENT_ID / ZEMAIL_GOOGLE_CLIENT_SECRET), a GOOGLE_CLIENT_SECRETS_FILE path, or a locally saved google_client.json. - New set_google_credentials MCP tool + GoogleCredentialsRequired error with clear setup instructions when no client is configured. - Pass the new env vars through .mcp.json; document them in plugin.json setup, the README Setup section, the search-emails skill, and .env.example (placeholders only — no real secrets). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
gmail.readonlyis a Google restricted scope. A single shared ZeroEntropy-owned OAuth app must pass Google verification (a CASA security audit, ~$8k plus extensive requirements) before external users can authorize without the "unverified app" cap / warnings. To ship without that, this changes auth so each user brings their own Google OAuth client — authorization then runs against a Google Cloud project the user controls, and using your own client for your own account needs no verification.Current vs new auth
Before:
zemail/gmail_client.pyhardcoded a single shared OAuth client (_OAUTH_CLIENT_CONFIGwith a baked-inclient_id+client_secretfor thezerank-2project). Every user authorized through that one ZeroEntropy app, which is what triggers the restricted-scope verification requirement.After: the hardcoded client is removed.
config.get_google_client_config()resolves the user's own OAuth client, mirroring exactly how the existingZEROENTROPY_API_KEYis handled (env var → local file fallback). Resolution order:ZEMAIL_GOOGLE_CLIENT_ID+ZEMAIL_GOOGLE_CLIENT_SECRETenv vars.GOOGLE_CLIENT_SECRETS_FILE— path to aclient_secret_*.jsondownloaded from the Google Cloud Console (supportsinstalledandwebshapes).google_client.jsonsaved in the data dir via the newset_google_credentialsMCP tool.When none are configured, Gmail tools return a
GoogleCredentialsRequiredmessage with step-by-step setup instructions instead of silently using a shared app.Interpretation chosen
The task allowed BYO client credentials, a user-provided token, or a service account. BYO OAuth client is the right fit here because: (a) it keeps the existing installed-app/loopback OAuth flow and
gmail.readonlyscope intact (minimal change), (b) a service account can't read a normal consumer Gmail mailbox without domain-wide delegation (Workspace-only), and (c) the credential-handling pattern matches the existing ZeroEntropy API key plumbing. A raw user-supplied token alone wouldn't support the refresh flow already inget_gmail_service.User setup (now in README "Setup")
set_google_credentials, theZEMAIL_GOOGLE_CLIENT_ID/ZEMAIL_GOOGLE_CLIENT_SECRETenv vars (see.env.example), orGOOGLE_CLIENT_SECRETS_FILE.Changes
zemail/config.py—get_google_client_config,save_google_client, setup message.zemail/gmail_client.py— removed_OAUTH_CLIENT_CONFIG; flows now use the resolved client; newGoogleCredentialsRequired.zemail/server.py— newset_google_credentialstool; Gmail tools handleGoogleCredentialsRequired..mcp.json/.claude-plugin/plugin.json— pass through / document the new env vars.README.md,skills/search-emails/SKILL.md,.env.example— setup docs (placeholders only).Verification done (no real Google creds used)
uv syncsucceeds.set_google_credentials).${...}treated as unset, savedgoogle_client.json, andGOOGLE_CLIENT_SECRETS_FILE— in an isolated temp data dir.GoogleCredentialsRequiredwith the setup steps (not a shared-app fallback).set_google_credentialsvalidates client-ID format and rejects empty secrets.Needs the owner's live verification / follow-up
zerank-2client_id/secret remain in git history (the initial commit). Now unused — revoke/rotate it in the Google Cloud Console.urlparseingmail_client.py) left untouched as it's unrelated to this change and predates it onmaster.🤖 Generated with Claude Code