Update oauth2 scopes

Seth Troisi committed May 11, 2026 at 17:05 UTC ff071d3f33dbd1fea20f6ba1743bf4ddcfc3289d
7 files changed +35 -15
AGENTS.md
+1 -1
@@ -6,7 +6,7 @@
6 - **Client**: `ColabClient` handles API interactions (assignment, unassignment).
7 - **Auth**: `auth.py` exposes a single `get_credentials(config_path, provider)` facade that dispatches on the `AuthProvider` enum. Two providers are supported, selected via the global `--auth=oauth2|adc` flag (default `oauth2`):
8 - `oauth2`: public `google-auth-oauthlib` `InstalledAppFlow`, token cached at `~/.config/colab-cli/token.json`. Requires an explicit client OAuth config (`-c/--client-oauth-config`, default `~/.colab-cli-oauth-config.json`); the previously-bundled `oauth_config.json` resource fallback was removed (commit `20eb88e`).
9 - - `adc`: Google Application Default Credentials via `google.auth.default()`. The CLI passes `scopes=PUBLIC_SCOPES` (which includes `colaboratory`) and re-applies via `creds.with_scopes()` for credential types that support it. **User credentials minted by `gcloud auth application-default login` ignore the `scopes=` kwarg AND raise `NotImplementedError` on `with_scopes`**: ADC users must explicitly re-authenticate with `gcloud auth application-default login --scopes=https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`. **Both scopes are required**: `userinfo.email` for the session backend at `colab.research.google.com` (assign/unassign/sessions return 401 without it), and `colaboratory` for the `RuntimeService` at `colab.pa.googleapis.com` (keep-alive returns 403 without it). Service-account / GCE / GKE / impersonated creds get the right scopes transparently via `with_scopes`.
9 + - `adc`: Google Application Default Credentials via `google.auth.default()`. The CLI passes `scopes=PUBLIC_SCOPES` (which includes `colaboratory`) and re-applies via `creds.with_scopes()` for credential types that support it. **User credentials minted by `gcloud auth application-default login` ignore the `scopes=` kwarg AND raise `NotImplementedError` on `with_scopes`**: ADC users must explicitly re-authenticate with `gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`. `userinfo.email` is required by the session backend at `colab.research.google.com` (assign/unassign/sessions return 401 without it); `colaboratory` is required by the `RuntimeService` at `colab.pa.googleapis.com` (keep-alive returns 403 without it); `openid` and `cloud-platform` are mandated by `gcloud` itself, which rejects scope lists that omit `cloud-platform` with `Invalid value for [--scopes]`. Service-account / GCE / GKE / impersonated creds get the right scopes transparently via `with_scopes`.
10 - **Backend Hosts**: Two distinct backends with different requirements:
11 - `colab.research.google.com` (session backend / `tun/m/...`): accepts the `userinfo.email` scope.
12 - `colab.pa.googleapis.com` (`RuntimeService`, used by `KeepAliveAssignment`): requires (a) the `colaboratory` OAuth scope, AND (b) `X-Goog-Api-Client` header containing the substring `grpc-web`. Both are enforced server-side; missing either yields HTTP 400 / 403 with descriptive `google.rpc.DebugInfo` payloads. Always log `response_body` on failure for these RPCs to avoid silent debugging.
docs/04_automation_and_utility.md
+9 -4
@@ -62,14 +62,19 @@ How each provider supplies the scope:
62
63 ```
64 gcloud auth application-default login \
65 - --scopes=https://www.googleapis.com/auth/userinfo.email,\
65 + --scopes=openid,\
66 + https://www.googleapis.com/auth/cloud-platform,\
67 + https://www.googleapis.com/auth/userinfo.email,\
68 https://www.googleapis.com/auth/colaboratory
69 ```
70
69 - Both scopes are required: `userinfo.email` for the session backend at
71 + `userinfo.email` is required for the session backend at
72 `colab.research.google.com` (otherwise assign/unassign/sessions return
71 - HTTP 401), and `colaboratory` for the `RuntimeService` at
72 - `colab.pa.googleapis.com` (otherwise keep-alive returns HTTP 403).
73 + HTTP 401); `colaboratory` is required for the `RuntimeService` at
74 + `colab.pa.googleapis.com` (otherwise keep-alive returns HTTP 403);
75 + `openid` and `cloud-platform` are mandated by `gcloud` itself
76 + (`gcloud auth application-default login` rejects scope lists that
77 + omit `cloud-platform` with `Invalid value for [--scopes]`).
78
79 `colab new` performs a one-shot keep-alive pre-flight after `assign`
80 succeeds so missing-scope failures surface immediately (with per-provider
docs/demos.md
+1 -1
@@ -6,7 +6,7 @@
6 Eleven scenarios that exercise common workflows, plus a final "bridging back to the browser" example. Every `colab` invocation below was actually executed; the text inside each `output` block was captured verbatim from stdout/stderr.
7
8 **Methodology**
9 -- Auth: `--auth=adc`. To set up: `gcloud auth application-default login --scopes=https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`.
9 +- Auth: `--auth=adc`. To set up: `gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`.
10 - Accelerator: every session uses **CPU**. Provisioning real accelerators is gated by per-account quota and would not work for most readers; the workflows themselves are accelerator-agnostic, so where a demo's narrative mentions a GPU or TPU the prose flags the substitution.
11 - Interactive subcommands — `colab auth`, `colab drivemount`, and unpiped `colab repl` / `colab console` — are **not run** here because they require human interaction at a TTY. Demos that would normally use them include an inline note explaining what they do and the workflow continues with the non-interactive parts.
12 - `enable_update_check` is set to `false` in `~/.config/colab-cli/settings.json` for the duration of recording so the daily upgrade banner doesn't pollute output.
integration/repro_keep_alive/test.sh
+7 -3
@@ -42,9 +42,11 @@ elif command -v gcloud > /dev/null && gcloud auth application-default print-acce
42 AUTH_FLAGS="--auth=adc"
43 else
44 echo "Error: ADC token lacks the required scopes."
45 - echo "Re-issue ADC creds with both required scopes:"
45 + echo "Re-issue ADC creds with all required scopes:"
46 echo " gcloud auth application-default login \\"
47 - echo " --scopes=https://www.googleapis.com/auth/userinfo.email,\\"
47 + echo " --scopes=openid,\\"
48 + echo " https://www.googleapis.com/auth/cloud-platform,\\"
49 + echo " https://www.googleapis.com/auth/userinfo.email,\\"
50 echo " https://www.googleapis.com/auth/colaboratory"
51 exit 1
52 fi
@@ -53,7 +55,9 @@ else
55 echo "Options:"
56 echo " - OAuth2: run 'uv run colab --auth=oauth2 sessions' to bootstrap"
57 echo " - ADC: gcloud auth application-default login \\"
56 - echo " --scopes=https://www.googleapis.com/auth/userinfo.email,\\"
58 + echo " --scopes=openid,\\"
59 + echo " https://www.googleapis.com/auth/cloud-platform,\\"
60 + echo " https://www.googleapis.com/auth/userinfo.email,\\"
61 echo " https://www.googleapis.com/auth/colaboratory"
62 exit 1
63 fi
integration/repro_keep_alive_scope/test.sh
+9 -3
@@ -65,7 +65,9 @@ elif command -v gcloud > /dev/null && gcloud auth application-default print-acce
65 echo "Skipping: ADC token lacks required scopes (need both"
66 echo " userinfo.email and colaboratory). Re-issue with:"
67 echo " gcloud auth application-default login \\"
68 - echo " --scopes=https://www.googleapis.com/auth/userinfo.email,\\"
68 + echo " --scopes=openid,\\"
69 + echo " https://www.googleapis.com/auth/cloud-platform,\\"
70 + echo " https://www.googleapis.com/auth/userinfo.email,\\"
71 echo " https://www.googleapis.com/auth/colaboratory"
72 exit 0 # environment-not-applicable
73 fi
@@ -74,7 +76,9 @@ else
76 echo " Bootstrap options:"
77 echo " - OAuth2: 'uv run colab --auth=oauth2 sessions' (browser consent)"
78 echo " - ADC: gcloud auth application-default login \\"
77 - echo " --scopes=https://www.googleapis.com/auth/userinfo.email,\\"
79 + echo " --scopes=openid,\\"
80 + echo " https://www.googleapis.com/auth/cloud-platform,\\"
81 + echo " https://www.googleapis.com/auth/userinfo.email,\\"
82 echo " https://www.googleapis.com/auth/colaboratory"
83 exit 0 # environment-not-applicable
84 fi
@@ -97,7 +101,9 @@ if ! uv run colab $AUTH_FLAGS --config "$SESSION_FILE" new -s "$SESSION_NAME"; t
101 echo "[FAILURE] 'colab new' failed. If this is a SCOPE_NOT_PERMITTED error,"
102 echo " the colaboratory scope is missing from your auth provider."
103 echo " For ADC: gcloud auth application-default login \\"
100 - echo " --scopes=https://www.googleapis.com/auth/cloud-platform,\\"
104 + echo " --scopes=openid,\\"
105 + echo " https://www.googleapis.com/auth/cloud-platform,\\"
106 + echo " https://www.googleapis.com/auth/userinfo.email,\\"
107 echo " https://www.googleapis.com/auth/colaboratory"
108 exit 1
109 fi
src/colab_cli/auth.py
+3 -1
@@ -112,7 +112,9 @@ def _get_adc_credentials() -> Credentials:
112 support `with_scopes`; user credentials minted by
113 `gcloud auth application-default login` do not. For the latter, the user
114 must re-run `gcloud auth application-default login` with
115 - `--scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/colaboratory`.
115 + `--scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory`
116 + (`openid` and `cloud-platform` are required by `gcloud` itself; `userinfo.email`
117 + is required by the session backend; `colaboratory` is required by this RPC).
118 """
119 creds, _ = google.auth.default(scopes=list(PUBLIC_SCOPES))
120 # Some credential subclasses ignore the `scopes=` kwarg in `default()`
src/colab_cli/commands/session.py
+5 -2
@@ -63,9 +63,12 @@ def _scope_remediation_message(provider) -> str:
63 "Re-authenticate ADC with both userinfo.email (required by the "
64 "Colab session backend at colab.research.google.com) and "
65 "colaboratory (required by the runtime service at "
66 - "colab.pa.googleapis.com):\n"
66 + "colab.pa.googleapis.com). The cloud-platform and openid scopes "
67 + "are required by gcloud itself:\n"
68 " gcloud auth application-default login \\\n"
68 - " --scopes=https://www.googleapis.com/auth/userinfo.email,"
69 + " --scopes=openid,"
70 + "https://www.googleapis.com/auth/cloud-platform,"
71 + "https://www.googleapis.com/auth/userinfo.email,"
72 "https://www.googleapis.com/auth/colaboratory\n"
73 "Then re-run `colab new`."
74 )