You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(gchat): accept endpointUrl as a direct-webhook JWT audience
When a Google Chat app is configured with **HTTP endpoint URL** as its
authentication audience (the recommended option for HTTP-hosted apps not
behind Cloud Run IAM), Google issues OIDC tokens whose `aud` is the
endpoint URL rather than the GCP project number. The adapter previously
only verified against `googleChatProjectNumber`, so URL-audience tokens
always 401'd.
Verify the bearer token against `googleChatProjectNumber` and/or an
explicitly-configured `endpointUrl`, accepting either when both are set.
The constructor's fail-closed check now also accepts an explicit
`endpointUrl` as a valid direct-webhook verifier. Auto-detected endpoint
URLs (populated from the request URL inside `handleWebhook`) are
intentionally NOT promoted to verifier status — that would let a caller
hitting the bot at any URL bypass verification.
Tests cover the URL-audience-only path, the both-audiences path, and
the auto-detected-URL-must-not-bypass-verification regression.
Co-authored-by: Cursor <cursoragent@cursor.com>
"GCP project number for direct webhook JWT verification.",
114
+
"GCP project number for direct webhook JWT verification. Use when the Chat app's authentication audience is set to 'Project number'.",
115
+
},
116
+
endpointUrl: {
117
+
type: "string",
118
+
description:
119
+
"Public URL of the webhook endpoint. Required for routing button click actions to your app, and used as an accepted JWT audience for direct webhooks when the Chat app's authentication audience is set to 'HTTP endpoint URL'.",
One of `googleChatProjectNumber`, `pubsubAudience`, or `disableSignatureVerification: true` is required — the constructor throws otherwise. Configure the verifier(s) for each transport you actually receive.
133
+
One of `googleChatProjectNumber`, `endpointUrl`, `pubsubAudience`, or `disableSignatureVerification: true` is required — the constructor throws otherwise. Configure the verifier(s) for each transport you actually receive.
129
134
130
135
## Authentication
131
136
@@ -196,10 +201,25 @@ Required for Workspace Events subscriptions and initiating DMs.
196
201
197
202
The two transports share one HTTP endpoint, so each verifier only covers its own request shape:
198
203
199
-
-**Direct webhooks** — Google Chat sends a signed JWT whose `aud` claim is your GCP project number. Configure with `googleChatProjectNumber`.
204
+
-**Direct webhooks** — Google Chat sends a signed JWT in the `Authorization: Bearer …` header. The expected `aud` claim depends on how the Chat app is configured (see [Verify requests from Google Chat](https://developers.google.com/workspace/chat/verify-requests-from-chat)).
200
205
-**Pub/Sub push** — Cloud Pub/Sub sends a signed OIDC JWT whose audience is whatever you configured on the push subscription. Configure with `pubsubAudience`.
201
206
202
-
If you only configure `googleChatProjectNumber`, incoming Pub/Sub-shaped requests are rejected with HTTP 401 — and vice versa. Configure both if you receive both.
207
+
If you only configure a direct-webhook verifier, incoming Pub/Sub-shaped requests are rejected with HTTP 401 — and vice versa. Configure both transports if you receive both.
|**Workspace Add-on Chat app** (built via Google Workspace Marketplace SDK; the audience is hardcoded) | endpoint URL |`service-{projectNumber}@gcp-sa-gsuiteaddons.iam.gserviceaccount.com`|`endpointUrl`|
216
+
| Mixed across envs / not sure | varies | varies | both `googleChatProjectNumber` and `endpointUrl`|
217
+
218
+
When both `googleChatProjectNumber` and `endpointUrl` are set, either audience is accepted. If you don't know which mode your app uses, look at the JWT `email` claim of an incoming request — `gcp-sa-gsuiteaddons` means it's a Workspace Add-on (URL audience).
219
+
220
+
<Callouttype="info">
221
+
Workspace Add-on Chat apps don't expose an "Authentication audience" radio; their token `aud` is always the endpoint URL. Set `endpointUrl` for these.
// the operator has not explicitly opted into the unsafe path. Previously
259
270
// the adapter accepted any webhook in this state, allowing forged
260
271
// payloads to impersonate users / trigger handlers.
272
+
//
273
+
// `endpointUrl` counts as a direct-webhook verifier because Chat apps
274
+
// configured with "HTTP endpoint URL" as the authentication audience
275
+
// (Google's recommended setting for non-IAM-hosted apps) issue tokens
276
+
// whose `aud` is the endpoint URL rather than the project number.
261
277
if(
262
278
!(
263
279
this.googleChatProjectNumber||
280
+
this.endpointUrlIsAudience||
264
281
this.pubsubAudience||
265
282
this.disableSignatureVerification
266
283
)
267
284
){
268
285
thrownewValidationError(
269
286
"gchat",
270
-
"Webhook signature verification is required. Set googleChatProjectNumber (or GOOGLE_CHAT_PROJECT_NUMBER) for direct webhooks and/or pubsubAudience (or GOOGLE_CHAT_PUBSUB_AUDIENCE) for Pub/Sub. To accept unverified webhooks (NOT recommended in production), set disableSignatureVerification: true."
287
+
"Webhook signature verification is required. Set googleChatProjectNumber (or GOOGLE_CHAT_PROJECT_NUMBER) and/or endpointUrl for direct webhooks and/or pubsubAudience (or GOOGLE_CHAT_PUBSUB_AUDIENCE) for Pub/Sub. To accept unverified webhooks (NOT recommended in production), set disableSignatureVerification: true."
"Google Chat webhook verification is disabled. Set GOOGLE_CHAT_PROJECT_NUMBERor googleChatProjectNumber to verify incoming requests."
785
+
"Google Chat webhook verification is disabled. Set GOOGLE_CHAT_PROJECT_NUMBER, googleChatProjectNumber, or endpointUrl to verify incoming requests."
757
786
);
758
787
}
759
788
}else{
760
789
this.logger.warn(
761
-
"Rejected direct Google Chat webhook: googleChatProjectNumber is not configured. Set GOOGLE_CHAT_PROJECT_NUMBER, or set disableSignatureVerification to accept unverified payloads."
790
+
"Rejected direct Google Chat webhook: neither googleChatProjectNumber nor endpointUrl is configured. Set one of them, or set disableSignatureVerification to accept unverified payloads."
0 commit comments