Google OAuth · Consent

Your app requests three scopes. The user approves one. Now what?

Google's OAuth consent screen is no longer a single accept-or-reject button. On most modern client IDs, users see a checkbox list and can hand over Calendar access while refusing Gmail — a partial grant your app receives with no error, no warning, and no failed callback.

Apps written against the old all-or-nothing model do not crash at that moment. They do something worse: they call an API with a token that never carried the scope, surface a broken feature to a paying customer, and log an authorization error nobody connects back to a checkbox on a consent screen.

What granular consent actually changed

Google states the intent plainly in its developer documentation:

“With granular permissions, consumers get more fine-grained control over what account data they choose to share with each app.”Google for Developers — How to handle granular permissions (page last updated 26 May 2026)

The practical consequence is that the set of scopes you request and the set of scopes you receive are now two different things. Google's guidance is explicit that an application must check what scopes are granted by the users and cannot assume users grant all requested scopes.

If your authorization code was written before this shift — or copied from a tutorial that was — it almost certainly treats a successful token response as proof that every requested scope was approved. That assumption is the bug.

When the granular consent screen actually appears

It does not appear for every app. Google publishes an exact matrix, and it turns on the number and type of scopes in the authorization request. Sign-In scopes are email, profile and openid; everything else counts as a non-Sign-In scope.

Sign-In scopes requestedNon-Sign-In scopes requestedGranular consent screen
1–30Not applicable
1–31 or moreApplicable
01Not applicable
02 or moreApplicable

Two things are worth taking from that table. First, a login-only integration is untouched — request nothing but Sign-In scopes and the user still approves or denies the whole request. Second, the moment you add a single data scope alongside sign-in, you are in granular territory. Most real products cross that line on day one.

There is also a sequencing detail teams miss. When both kinds are requested, users consent to the Sign-In scopes first, on their own screen, and only then see the granular checkbox screen for the data scopes. A user can complete sign-in perfectly and still hand you nothing else.

Where this quietly breaks working products

Features that fail with no error path

A denied scope does not produce a failed callback. You receive an access token, your code proceeds as normal, and the API call fails much later — usually as a generic authorization error, far from the screen that caused it.

The legacy client-ID trap

The enable_granular_consent parameter only affects OAuth client IDs created before 2019; for newer clients granular permissions is always on. Once Google enables it for an application, the parameter stops having any effect at all — so teams reading it as a switch they control are reading it wrong.

A testing blind spot

Google's own testing guidance says to test with a personal Google Account rather than a Workspace account, because Workspace Enterprise apps with domain-wide delegation of authority — or apps marked Trusted — bypass the granular screen entirely. QA on a company account can pass while every consumer user gets a different flow.

Re-prompting the wrong way

Reacting to a refusal by immediately asking again is not an acceptable fix. Google's OAuth 2.0 policy permits a new authorization request only after the user clearly indicates an intent to use the feature that scope powers.

Scope drift against the Console

Your Cloud Console consent-screen configuration has to match the scopes your app actually sends. Teams adding and removing scopes while debugging partial consent routinely create a Data Access page scope mismatch, which is a separate failure surface with its own user-visible warning screen.

Grants you forgot you had

Token responses also include scopes approved in earlier sessions, and consent is recorded per user and per client ID. Reasoning about what a user just approved from a response that also carries historical grants is a common source of wrong logic.

This is a policy requirement, not a UX preference

The part most teams miss is that handling partial consent is written into Google's OAuth 2.0 Policies — the document that forms part of the Google APIs Terms of Service. It states:

“If a user doesn't grant a scope that you requested, you need to disable any related functionality in your app and not make any related API calls that will fail. If a user doesn't grant a requested scope, you may only request a new authorization after the user clearly indicates an intent to use the feature or functionality provided by the scope.”Google for Developers — OAuth 2.0 Policies (last modified 5 August 2026)

Read that as a compliance obligation, because that is what it is. An application that keeps calling APIs it knows will fail, or that reopens the consent dialog until the user gives in, is not merely rough around the edges — it is operating outside the policy it accepted when the client was registered.

It also changes how you should interpret your error logs. A partial grant does not announce itself; it shows up downstream as the same family of authorization failures covered in Google OAuth consent screen errors, which is exactly why the root cause gets misdiagnosed as a configuration problem for weeks.

The scope-minimisation angle nobody plans for

Granular consent quietly punishes over-requesting. Google's policy already requires you to request only the smallest set of scopes necessary for functionality the user knowingly chose — and the granular screen now puts that judgement in front of the user, itemised. Ask for six scopes at first sign-in and you have not just risked a policy finding; you have created six separate opportunities for someone to say no before they have seen any value from your product.

The alternative Google recommends is incremental authorization: request a scope in the context of the feature that needs it, at the moment it is needed, with a plain-language justification shown first. It is more work to build than one large consent prompt at sign-up. It also converts better, because the ask arrives when the user already wants the thing it unlocks.

How far you can push that pattern depends on how Google classifies each scope you need, which is decided by Google and not by you — the tiers and their consequences are covered in sensitive vs restricted scopes.

How this gets handled as a piece of work

  1. Audit what you actually requestEvery authorization entry point in the product is inventoried — SDK initialisation, manifest files, outgoing authorization URLs — to establish which flows trigger the granular screen and which do not. Most teams are surprised by at least one.
  2. Map each scope to a feature and a failure modeFor every scope: what breaks if it is refused, what the user should see instead, and whether that feature should be hidden, disabled, or offered with a contextual re-request later.
  3. Rework the grant checkThe token response becomes the source of truth for what was approved, using the granted-scope checks your platform exposes, instead of assuming the request list was honoured in full.
  4. Split oversized prompts into incremental authorizationBundled first-run consent screens are broken up so scopes are requested in context with a justification shown beforehand — the pattern Google's policy asks for and the one that survives review scrutiny best.
  5. Test against real refusalsEach partial-grant combination is exercised on an account type that actually shows the granular screen, so the behaviour signed off in QA is the behaviour consumer users get.

None of these steps is exotic on its own. What makes the work expensive is that it touches authorization, UI state and error handling at the same time, and that the failure it prevents stays invisible until a real user unticks a real checkbox in production.

Common mistakes we see

Treating the token as proof of consent

An access token was issued. That is all it tells you. The granted-scope list in the response is the only reliable statement of what the user actually approved.

Bundling everything into first-run sign-in

Asking a first-time user for a stack of unfamiliar permissions before showing any value is both a policy risk and a conversion problem. It is also the single most common cause of partial grants.

Testing only on a Workspace account

Domain-wide delegation and Trusted app status bypass the granular screen. If that is the only account type used in QA, the entire partial-consent path ships untested.

Looping the consent dialog on refusal

Re-asking immediately after a refusal is explicitly outside Google's policy. Consent may be requested again only once the user shows intent to use the relevant feature.

Where teams lose the most time

The expensive part of this problem is rarely the code change. It is the weeks spent chasing an intermittent authorization error reported by a fraction of users, before anyone connects it to a checkbox nobody knew existed. Logging the granted scope set at token issue — not just the requested set — turns a fortnight of guesswork into a single query.

Accuracy note. The conditions under which the granular consent screen appears, the exception for Google Workspace apps with domain-wide delegation of authority or Trusted status, the behaviour of the enable_granular_consent parameter, and the partial-consent handling requirement are all taken from Google's published documentation — the granular permissions guide (last updated 26 May 2026) and the OAuth 2.0 Policies page (last modified 5 August 2026). Google does not publish a stated position on how partial-consent handling is weighted during app verification review, and no such claim is made here. Scope classification, review outcomes and review timelines are determined by Google alone; this page describes preparation and technical implementation support, not any assured review result.