Skip to main content
CARLA HQ
#OAuth#Google Sheets#Security#BuildingInPublic

Escaping Google's OAuth Purgatory for a Local AI Chrome Extension

Aug 6, 20266 min read
Daniel Münch(Carla HQ Founder)

If you build a tool that interacts with Google Workspace, you eventually face the final boss of deployment: the Google Trust & Safety OAuth verification review.

Three weeks ago, I published the private beta of Carla, capped at 100 users. That limit was not arbitrary. Unverified Google Cloud projects in internal testing mode cap out at 100 test users. Unverified projects also trigger the “Unverified App” warning, which undermines user trust. Getting the project verified required architectural maneuvering, policy wrestling, and patience. Here is how the process works, why Google pushed back, and how I got the scopes approved.

Why is unverified OAuth capped at 100 users?

Before an OAuth consent screen is verified, Google keeps your Cloud project in testing mode. This imposes a hard-coded cap of 100 test users.

This created an onboarding headache for my initial cohort. To let a single user into the private beta, I had to allow-list their email address in two places: the Google Cloud OAuth test list and the Chrome Web Store tester list.

Getting the consent screen verified pushes the app to production status, lifting the 100-user cap for OAuth. Now I have unlimited OAuth test users and only manage the allow-list on the Chrome Web Store side.

Whenever you use an app that requests “Sign in with Google” or asks for Drive access, you see the OAuth consent screen. It’s the trust bridge between the user, Google, and the developer.

To protect users from malicious apps, Google limits access to sensitive scopes like reading or writing spreadsheets. If your app requests these scopes, you must submit your Google Cloud project to the Trust & Safety team to prove why you need access and how you secure the data.

Why Carla needs access

Carla is a Chrome extension designed to run TabICL inference locally inside Google Sheets. To do this, the extension must:

  • Read tabular data from the active spreadsheet tab.
  • Load that data into local browser memory for processing by our offline WebAssembly/WebGPU engine.
  • Write classification labels into a new column on your active sheet.

To accomplish this, I requested the https://www.googleapis.com/auth/spreadsheets scope. That’s where the friction started.

Why did Google reject the spreadsheets scope?

Google’s automated review system rejected the spreadsheets scope. Their stance is that this scope grants continuous offline access to all user files, violating minimum privilege.

They offered two alternatives:

  • spreadsheets.currentonly: This sounds ideal, but it’s a trap. Google’s documentation notes this is an Apps Script concept restricted to container-bound scripts. It does not work for standard OAuth 2.0 REST clients making external HTTPS calls.
  • drive.file: This requires integrating the Google Picker API. For an active-tab Chrome extension, forcing a user to open a pop-up file picker to search for and select the spreadsheet they are already looking at breaks the core workflow.

The AI policy flag

Because Carla uses machine learning, Trust & Safety flagged the project under their Limited Use policy, assuming the app transmitted Workspace data to third-party providers like OpenAI or Anthropic to train models.

This was a lower hurdle. I documented that Carla’s architecture is strictly offline. By running models locally via WebGPU, plaintext data never leaves localhost. Updating the privacy policy with Google’s Limited Use compliance statement cleared the flag.

How did removing the unused backend client solve verification?

My initial instinct was to argue that Google’s suggested scopes created poor user experience. That is a losing battle. Google explicitly states UI/UX preferences are not valid reasons for scope exceptions.

The breakthrough came from identifying the root cause of Google’s pushback: the presence of an unused Web Application Client ID.

Carla’s Chrome extension (chrome.identity) had always used the Implicit Flow from day one, issuing short-lived access tokens without a Client Secret. However, because the Google Cloud project also contained a Web Application Client ID (even though the extension never used it), Trust & Safety flagged the project under the assumption that a backend server could execute the Authorization Code Flow to obtain Refresh Tokens for continuous offline access.

⚠️ What the Unused Web App Client ID Enabled — Google's Fear Browser / Extension User active tab session Backend Server Stores Client Secret Google OAuth Server OAuth 2.0 Authorization 🗄️ User Spreadsheet Data (Google Drive / Sheets) Risk: Continuous Background Offline Access via Refresh Token 1. Auth Code 2. Code + Client Secret 3. Token + REFRESH TOKEN Continuous Offline Access

By deleting the unused Web Application Client ID from the Google Cloud project entirely, I eliminated the backend attack surface. Proving that access was strictly ephemeral and bounded to active browser sessions backed the review process into a corner where approving the spreadsheets scope was the only logical outcome.

✅ What Carla Actually Uses — Chrome Extension Client ID Only Chrome Extension chrome.identity (Implicit Flow) Google OAuth Server Chrome Extension Client ID 🔒 Active Session Google Sheets Data Ephemeral Session Token ONLY — Zero Background Server Access — Zero Refresh Token 1. Interactive Login 2. Ephemeral Token ONLY Active Session Access Only

The waiting game

Once that technical response was submitted, the automated rejections stopped. Server logs showed hits from Ashburn data centers and reviewers in Hyderabad navigating the privacy policy. The ticket escalated to a Tier 2 manual review.

The timing worked out well. I went offline for a two-week family trip to the Brittany coast in Plougasnou while the OAuth review processed in the background.

When I returned from Brittany, the approval notification was in my inbox.

With the OAuth hurdle cleared, the next stop is the Chrome Web Store review. Now we test whether the WebAssembly bundle moves through just as smoothly.

What comes next?

Carla remains in private beta while the Chrome Web Store review is pending.

If you want early access to test local TabICL inference inside Google Sheets before public store availability, request access via our private beta list.

Key takeaways for builders

If you are navigating Google Cloud OAuth verification for a client-side or extension app:

  • Do not argue UX, argue attack surface. Google ignores user friction arguments. Show how your architecture makes continuous access impossible.
  • Separate client IDs. Delete backend server Client IDs from your project if your app executes strictly client-side.
  • Keep tokens short-lived and ephemeral. Eliminating refresh tokens removes the primary risk profile Google Trust & Safety checks for.
Daniel Münch

Daniel Münch

Carla HQ Founder

Seasoned software engineer and applied mathematician with 15+ years of experience transforming complex challenges into scalable solutions across biomedical imaging, HrTech, PropTech, and FinTech domains.

← Back to all articles