Skip to content

fix(gchat): bind add-on webhook verification to a configured identity - #787

Merged
dancer merged 4 commits into
mainfrom
josh/gchat-addon-identity
Aug 5, 2026
Merged

fix(gchat): bind add-on webhook verification to a configured identity#787
dancer merged 4 commits into
mainfrom
josh/gchat-addon-identity

Conversation

@dancer

@dancer dancer commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

summary

endpoint-URL webhook verification accepted any email claim matching the generic Workspace Add-on shape:

/^service-\d+@gcp-sa-gsuiteaddons\.iam\.gserviceaccount\.com$/

the \d+ is a GCP project number, and service agents are service-{PROJECT_NUMBER}@gcp-sa-{SERVICE}... for the project that owns them. so that shape identifies "some Workspace Add-on", not this app's add-on, and it was the only thing standing between a public endpoint URL and a verified request. the method's own doc comment already stated the correct invariant, that the token is only trustworthy if it was issued to Google Chat itself

adds workspaceAddOnServiceAccountEmail (env GOOGLE_CHAT_WORKSPACE_ADDON_SERVICE_ACCOUNT_EMAIL) and compares add-on identities exactly. when it is unset, add-on-shaped tokens are rejected rather than trusted by shape, with a log naming the option to set

chat@system.gserviceaccount.com is untouched, so standalone Chat apps behave exactly as before. the project-number and Pub/Sub paths were already bound to exact identities and are unchanged

behavior

token email before after
chat@system.gserviceaccount.com accept accept
add-on shape, matches configured identity accept accept
add-on shape, different project accept reject
add-on shape, option unset accept reject
why not reject at construction

refusing to initialize when the option is absent would be the stricter-looking choice, but the adapter cannot tell Workspace Add-on mode from config alone, it only sees endpointUrl. throwing there would break every ordinary endpoint-URL Chat app. rejecting add-on-shaped tokens at verification is the precise equivalent without the collateral

test plan

  • an add-on token matching the configured identity is accepted
  • an add-on token from a different project is rejected, the case the generic shape allowed
  • an add-on token is rejected when no identity is configured
  • chat@system.gserviceaccount.com is still accepted with no add-on config
  • suffixed and prefixed lookalike domains, an uppercase variant, and trailing whitespace are all rejected
  • a matching identity with email_verified: false is rejected

the two rejection cases above returned 200 before this change and 401 after

@dancer
dancer requested a review from a team as a code owner August 5, 2026 10:20
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview, v0 Aug 5, 2026 10:34am
chat-sdk-nextjs-chat Ready Ready Preview Aug 5, 2026 10:34am

@dancer
dancer merged commit 7a19223 into main Aug 5, 2026
18 checks passed
@dancer
dancer deleted the josh/gchat-addon-identity branch August 5, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants