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): verify project-number tokens against Chat issuer certs; infer endpoint URL only after verification
Two fixes to the direct-webhook verification introduced in this PR:
1. Project-number-audience tokens are self-signed JWTs from
chat@system.gserviceaccount.com, not OIDC ID tokens. verifyIdToken can
never validate them: it checks Google's OIDC federated certs and only
accepts accounts.google.com issuers, so the previous iss claim check was
unreachable and real project-number tokens always failed. Verify them per
Google's reference implementation instead: verifySignedJwtWithCertsAsync
against the Chat service account's X.509 certs (cached 1h) with issuer
chat@system.gserviceaccount.com. Endpoint-URL tokens keep the OIDC
verifyIdToken path plus email/email_verified claim checks. When both
verifiers are configured, either token type is accepted.
2. Move button-click endpoint URL inference after successful verification.
Previously an unauthenticated request (401) could still poison
inferredEndpointUrl via a spoofed Host header, first-write-wins, and the
poisoned URL flowed into every outbound card's action routing.
Adds regression tests for both; updates docs, README, and the changeset.
|**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).
211
+
| Your Chat app |Token type & `aud`| Signed by | Set |
| Standalone Chat app, **Authentication audience: Project number** (in Chat API config) |self-signed JWT, `aud` = project number |`chat@system.gserviceaccount.com`(its own X.509 certs)|`googleChatProjectNumber`|
214
+
| Standalone Chat app, **Authentication audience: HTTP endpoint URL**|Google OIDC ID token, `aud` = endpoint URL | Google (`email`: `chat@system.gserviceaccount.com`)|`endpointUrl`|
215
+
|**Workspace Add-on Chat app** (built via Google Workspace Marketplace SDK; the audience is hardcoded) |Google OIDC ID token, `aud` = endpoint URL | Google (`email`: `service-{projectNumber}@gcp-sa-gsuiteaddons.iam.gserviceaccount.com`)|`endpointUrl`|
216
+
| Mixed across envs / not sure | varies | varies | both `googleChatProjectNumber` and `endpointUrl`|
217
+
218
+
The two token types are verified differently, matching [Google's reference implementation](https://developers.google.com/workspace/chat/verify-requests-from-chat): endpoint-URL tokens are standard OIDC ID tokens checked against Google's public certs plus the Chat service-account `email` claim; project-number tokens are self-signed by `chat@system.gserviceaccount.com` and checked against that service account's own X.509 certificates. When both `googleChatProjectNumber` and `endpointUrl` are set, either token type is accepted. If you don't know which mode your app uses, look at an incoming token: an `email` claim containing`gcp-sa-gsuiteaddons` means it's a Workspace Add-on (URL audience).
219
219
220
220
<Callouttype="info">
221
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.
Copy file name to clipboardExpand all lines: packages/adapter-gchat/README.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -240,7 +240,9 @@ createGoogleChatAdapter({
240
240
});
241
241
```
242
242
243
-
Use `endpointUrl` when the setting is **HTTP endpoint URL**. Workspace Add-on Chat apps always use URL audience tokens. When both `googleChatProjectNumber` and `endpointUrl` are set, either audience is accepted.
243
+
Use `endpointUrl` when the setting is **HTTP endpoint URL**. Workspace Add-on Chat apps always use URL audience tokens. When both `googleChatProjectNumber` and `endpointUrl` are set, either token type is accepted.
244
+
245
+
The two modes carry different token types, and the adapter verifies each per [Google's reference implementation](https://developers.google.com/workspace/chat/verify-requests-from-chat): endpoint-URL tokens are standard Google OIDC ID tokens (checked against Google's public certs, plus the Chat service-account `email` claim with `email_verified`), while project-number tokens are JWTs self-signed by `chat@system.gserviceaccount.com` (checked against that service account's X.509 certificates with issuer `chat@system.gserviceaccount.com`). The configured `endpointUrl` must exactly match the URL registered in the Chat API console — a trailing-slash or scheme mismatch fails verification.
0 commit comments