BEN://
--:--:-- UTC
BEN://WRITING/GOOGLE-OAUTH-CONSENT
identity·Sep 25, 2026·6 min read

How Google's OAuth Consent Screen Actually Works

A practitioner's walkthrough of Google's OAuth verification tiers, scope categories, and the pitfalls (100-user caps, CASA audits, brand verification) that trip up anyone wiring an app into Gmail, Calendar, or Drive.

oauthgoogle-apiauthentication

CONTEXT

Any project that touches Gmail, Calendar, or Drive on a user's behalf — including agent tooling that needs to read a mailbox or write a calendar event — runs into Google's OAuth consent and verification system almost immediately. It's not optional paperwork; it changes what your app can do and how many users it can have before you've finished it.

The mechanics of OAuth 2.0 itself — authorization code, redirect URI, token exchange — are the easy part and well documented everywhere. The part that actually gates a project is Google's layer on top: what the consent screen shows, which scopes require review, and what happens to your app before that review completes. Get this wrong and you find out not at launch but weeks in, when your app silently stops letting in new users.

The three scope tiers

Google buckets every OAuth scope into one of three categories, and the category — not the API you're calling — determines what you have to do before going to production.

Most of the scopes an agent-style tool wants — read a mailbox, create Calendar events, list Drive files — land in the sensitive or restricted tier by default. calendar.events is sensitive; broad Gmail or Drive scopes are restricted. If you can get away with a narrower, purpose-built scope (Google has been adding these, e.g. Gmail's gmail.addons.current.message.readonly instead of full mailbox read) it's worth the trade of reduced functionality for a much lighter review.

Testing vs. production: the 100-user cap

Every OAuth client starts in Testing publishing status. In this state you add specific Google accounts as test users (typically capped around 100), those users see an "unverified app" warning before consent, and their authorization expires after 7 days, so they have to re-consent weekly. This is fine for development and fine for a genuinely internal tool with a fixed, small user list.

The moment you flip a client to In production without completing verification, a different and much sharper limit applies: Google caps the app at 100 total users, for the lifetime of that OAuth client — not 100 concurrent, not 100 per month, 100 ever. Creating a new OAuth client ID or redeploying the app does not reset it; the cap is tied to the Cloud project's client. There is no way to raise it short of completing verification.

This is the mistake that catches people off guard: an app looks done, ships to production, picks up a trickle of real users, and then new sign-ups start failing at exactly user 101 with no obvious error explaining why. If you know from the start that an app will have more than a handful of real users, budget for verification before launch rather than treating it as a later cleanup task.

What verification actually checks

Standard verification (for sensitive scopes) is a manual review, typically 2–3 business days once submitted, that checks:

Restricted scopes: CASA on top

If any requested scope is restricted (full Gmail, Drive, Fit, etc.), standard verification isn't the end of it. Google also requires a security assessment under CASA (Cloud Application Security Assessment), an audit framework built on OWASP's Application Security Verification Standard (ASVS) and performed by a Google-approved third-party assessor.

CASA is tiered by risk (assurance levels AL1/AL2), with the required level depending on user count, scopes requested, and how the app handles the data downstream (e.g., whether restricted data ever leaves Google's infrastructure to sit on your own servers). It is not free, it is not instant, and — this is the part people miss — it isn't one-and-done: apps have to be reassessed annually, and Google can bump the required tier if your user base or data handling changes. For a side project or an internal agent tool, this is often the deciding factor in whether to request the restricted scope at all versus finding a narrower alternative.

Exceptions worth knowing

Verification isn't required in a handful of specific cases: personal-use apps only you will ever authorize, apps confined to development/testing/staging, apps that only touch data the app itself owns (not other users' data), and apps used exclusively inside a single Google Workspace organization via domain-wide delegation. If your "app" is really a personal automation script hitting your own Gmail, you can often stay in Testing mode indefinitely and never trigger any of this — the moment it needs to work for someone else's account is the moment the rules above apply.

Practical sequence for a new integration

  1. Scope the request down first. Look for the narrowest scope that does the job before assuming you need the broad one — the difference between sensitive and restricted tiers is the difference between a few days of review and an ongoing paid audit.
  2. Verify the domain early. DNS propagation and Search Console confirmation can eat three days on their own; kick this off before you're ready to submit anything else.
  3. Write the scope justification and record the demo as you build, not after — it's much easier to narrate the actual feature than to reconstruct why you needed a scope six weeks later.
  4. Decide deliberately whether you need a restricted scope at all. If the answer is yes, treat the CASA assessment as a recurring line item, not a one-time gate, and budget for the annual re-audit.
  5. If the app truly has a fixed, small, known set of users, staying in Testing with those accounts explicitly added is a legitimate long-term posture — it avoids verification entirely, at the cost of the 7-day re-consent cadence and the up-front 100-test-user ceiling.

None of this is exotic once you've been through it once, but the failure mode — an app that works perfectly in every test, then hard-stops at 100 real users, or gets rejected for asking for more access than it demonstrably uses — is entirely avoidable by treating verification as part of the build, not an afterthought bolted on at launch.

← All writing