Google Cloud projects as OAuth boundaries

People arrive at Google Cloud Console with a simple picture: my Google account, the apps I trust, and what each app may do with my Drive / Gmail / Calendar.

Google Cloud answers with a different noun: the Project. Consent screens, API enablement, and quotas all hang off that Project. Client IDs are children of it. Personal "just let Composio read my Drive" work gets the same enterprise workflow Fortune 500 teams use for VMs and billing.

This page names the mismatch, shows an ideal model, then shows how to map today’s console onto that model without pretending the schema is fine.

Ideal mental model

What you actually care about as a person wiring tools:

Concept Job

You (account)

Identity and the data (Drive, mail, calendar). Quotas for "access my stuff" could live here.

App

A named trust boundary: Composio, rclone, a personal web app. Own branding, own consent copy, own scope set.

Client credentials

How that app proves itself during OAuth (Client ID / secret, redirect URIs).

Grant (token)

What you approved this app to do, for this session / refresh chain.

flowchart TB
  You["You (Google account + your data)"]
  subgraph Apps["Apps directory (ideal)"]
    A1["App: Composio\nconsent / scopes / branding"]
    A2["App: rclone\nconsent / scopes / branding"]
    A3["App: personal script\nconsent / scopes / branding"]
  end
  You -->|authorize grant| A1
  You -->|authorize grant| A2
  You -->|authorize grant| A3
  A1 --> C1[Client ID + secret]
  A2 --> C2[Client ID + secret]
  A3 --> C3[Client ID + secret]

In this world you would not invent a new "Personal 2.0" project every time you add a sync tool. Apps would be first-class. Infrastructure projects (VMs, BigQuery, Cloud Run) would be optional and separate.

Ideal mental model: You authorize separate apps; each app owns consent and client credentials
Figure 1. Ideal: account, apps, credentials

What Google Cloud actually couples

In the Console today, several concerns that feel like "app" properties are project-wide:

Concern Ideal owner Actual GCP owner

OAuth consent screen (name, support email, scopes list)

App

Project (one screen shared by every Client ID in that project)

API enablement (Drive, Gmail, …​)

App or client

Project

API quotas / rate limits

App or user sandbox

Project

OAuth Client ID + redirect URIs

App

Credential under Project (but consent still project-wide)

Billing / IAM for cloud resources

Infrastructure project

Project (same object)

flowchart TB
  subgraph Proj["Google Cloud Project (actual)"]
    Consent["OAuth consent screen\n(shared)"]
    APIs["Enabled APIs"]
    Quota["API quotas"]
    Creds["OAuth Client IDs"]
    Consent --- Creds
    APIs --- Quota
  end
  User[Your Google account]
  User -->|sees project app name + union of scopes| Consent
  Creds -->|Client ID A| ToolA[rclone]
  Creds -->|Client ID B| ToolB[Composio]

Consequences people feel in the UI:

  • Two Client IDs in one project still share one consent screen and the union of declared scopes.

  • Revoking or resetting trust for "that project app" can couple token lifetimes across tools you thought were separate.

  • Heavy Drive use from rclone can exhaust project quota and starve Composio (or the reverse).

  • Pure consumer workflows (NotebookLM context via Drive) still require a Project, consent screen, and Client ID—​there is no personal API sandbox.

Actual model: one Project shares consent screen, APIs, and quotas across Client IDs
Figure 2. Actual: Project owns the shared bundle

Mapping ideal → Console (without self-deception)

Keep the ideal nouns in your head. Label Projects as stand-ins for apps (or for trust platforms), not as "folders for personal stuff."

Mapping: Composio and rclone each get their own Project used as a trust platform
Figure 3. Map ideal apps onto Projects
flowchart LR
  subgraph Ideal["Ideal"]
    I1[App: Composio]
    I2[App: rclone]
  end
  subgraph Map["Map onto GCP"]
    P1["Project: composio-integrations\n= trust platform for Composio"]
    P2["Project: rclone-personal\n= trust platform for rclone"]
  end
  I1 -.->|one project per trust boundary| P1
  I2 -.->|separate project| P2

Practical mapping rules:

Ideal intent What to create in GCP

One trust platform (e.g. all Google tools inside Composio)

One Project + one OAuth Client ID; grow scopes/APIs as you add Gmail, Calendar, Drive, …​

A different product with its own brand and revoke story (rclone, a hobby web app)

A separate Project (and its own Client ID)

Only cloud VMs / billing / IaC

A Project used as real infrastructure—​do not overload it as an OAuth app unless you accept coupling

"Personal catch-all"

Avoid. That is how consent names, scopes, quotas, and revokes tangle.

Lumping vs splitting

Lump when the tools share a platform and you want one mental revoke surface (recommended for "everything Google inside Composio"): same Project, same Client ID, enable APIs and add scopes as you grow, then re-authorize so tokens pick up new scopes.

Split when products are unrelated (rclone sync vs Composio agent tools): separate Projects so consent branding, scope unions, quotas, and revocation stay independent.

Do not put a second Client ID in an existing "Personal" project and assume isolation. You only isolated the credential string—​not consent, quotas, or API enablement.

Scopes, APIs, and lookalike traps

  • Enable the consumer API you actually call. NotebookLM-style access to docs in Drive uses Google Drive API, not Vertex AI Workbench / "Enterprise Notebooks."

  • Consent scopes are the human-visible permission set. Enabling an API without adding scopes (and re-authorizing) does not grant access.

  • Authorized redirect URIs are required for web-style OAuth callbacks (e.g. Composio’s callback). Authorized JavaScript origins are for browser clients; leave them empty when the tool only needs a redirect URI.

  • Expanding scopes does not rewrite old tokens—​open the connection again and complete OAuth.