Skip to content

fix(googlechat): restore verification certificate retrieval after headers regression (#76742)#76791

Closed
SymbolStar wants to merge 2 commits into
openclaw:mainfrom
SymbolStar:fix/googlechat-headers-has-76742
Closed

fix(googlechat): restore verification certificate retrieval after headers regression (#76742)#76791
SymbolStar wants to merge 2 commits into
openclaw:mainfrom
SymbolStar:fix/googlechat-headers-has-76742

Conversation

@SymbolStar

Copy link
Copy Markdown
Contributor

Fixes #76742

Root Cause

google-auth-library's AuthClient registers a DEFAULT_REQUEST_INTERCEPTOR that calls config.headers.has('x-goog-api-client'), expecting config.headers to be a native Headers instance.

After the stageRuntimeDependencies removal in ed8f50f, the bundled build's deep-clone utility (extend) used by gaxios's #prepareRequest can downgrade a Headers instance to a plain object whose prototype methods (.has(), .set(), etc.) are lost. This causes:

Google Chat webhook auth rejected: Failed to retrieve verification certificates: config.headers.has is not a function

when OAuth2Client.verifyIdToken()getFederatedSignonCertsAsync() fetches federated sign-on certificates through the shared Gaxios transport.

Fix

Add a headers-normalizing request interceptor to the shared Gaxios transport in getGoogleAuthTransport(). This interceptor runs before the AuthClient interceptor and converts any plain-object headers back to a proper Headers instance. If headers are already a Headers instance, they are left untouched.

Tests

  • Added test verifying plain-object headers are normalized to Headers instances
  • Added test verifying native Headers instances are passed through unchanged

…ders regression (openclaw#76742)

google-auth-library's AuthClient registers a request interceptor that
calls config.headers.has() expecting a native Headers instance.  After
the stageRuntimeDependencies removal (ed8f50f), the bundled build's
deep-clone utility (extend) can downgrade the Headers instance to a
plain object, causing 'config.headers.has is not a function' when
OAuth2Client.verifyIdToken() fetches federated sign-on certificates.

Add a headers-normalizing request interceptor to the shared Gaxios
transport that runs before the AuthClient interceptor, converting any
plain-object headers back to a proper Headers instance.
@openclaw-barnacle openclaw-barnacle Bot added channel: googlechat Channel integration: googlechat size: S labels May 3, 2026
@clawsweeper

clawsweeper Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I did a careful shell check against current main, and this is already implemented.

Current main already contains the Google Chat Google-auth header compatibility fix this PR was carrying, including request-header normalization, response-header normalization, focused tests, and changelog coverage; the later unsupported_grant_type comment is a separate token/grant failure surface, not the certificate-header regression fixed here.

So I’m closing this as already implemented rather than keeping a duplicate issue open.

Review details

Best possible solution:

Keep the plugin-owned header compatibility implementation on current main and track any remaining unsupported_grant_type token/grant failure separately if it still reproduces.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: Google Chat app-url verification reaches OAuth2Client.verifyIdToken(), google-auth-library reads request and response headers through Fetch Headers methods, and the tests cover the downgraded plain-object header shapes. I did not run a live Google Chat webhook in this read-only pass.

Is this the best way to solve the issue?

Yes: normalizing headers inside the Google Chat plugin's shared Google-auth transport is the narrow owner-local fix and preserves the SSRF-guarded fetch path. Current main also has the missing changelog coverage, so closing this now-obsolete PR is the best cleanup path.

Security review:

Security review cleared: The PR surface is limited to Google Chat auth runtime/tests, adds no dependencies or CI changes, and keeps Google auth requests on the existing SSRF-guarded transport.

What I checked:

Likely related people:

  • vincentkoc: Recent current-main history and the related merged fix(googlechat): harden google auth transport #69812 work tie this handle to the Google auth transport hardening, request-header normalization, and later transport isolation around the affected files. (role: recent Google Chat auth transport maintainer; confidence: high; commits: 6d6845ea9d23, 01e2755dc3c7, b31c001a2b51; files: extensions/googlechat/src/google-auth.runtime.ts, extensions/googlechat/src/google-auth.runtime.test.ts, extensions/googlechat/src/auth.ts)
  • steipete: The current-main proof commit that adds the response-header normalization and changelog coverage is authored by Peter Steinberger, whose maintainer handle is steipete. (role: current-main response-header fix author; confidence: high; commits: e5248789986c; files: extensions/googlechat/src/google-auth.runtime.ts, extensions/googlechat/src/google-auth.runtime.test.ts, CHANGELOG.md)

Codex review notes: model gpt-5.5, reasoning high; reviewed against da1e1435ad31; fix evidence: commit e5248789986c, main fix timestamp 2026-05-04T08:40:28+01:00.

@donbowman

Copy link
Copy Markdown

it changes, but doesn't resolve.

now I get this error:

"""
info channels/googlechat {"subsystem":"channels/googlechat"} [default] Google Chat webhook auth rejected: res?.headers.get is not a function
"""

@SymbolStar

Copy link
Copy Markdown
Contributor Author

Updated: this PR now also covers #76880 (reopen of #76742). Added a response interceptor that mirrors the existing request interceptor — normalizes plain-object response headers back to a native Headers instance, fixing res?.headers.get is not a function.

@donbowman

Copy link
Copy Markdown

That progresses, but now there's another error:

"""
02:40:48+00:00 error channels/googlechat {"subsystem":"channels/googlechat"} Failed sending typing message: Error: unsupported_grant_type: Invalid grant_type:
"""

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: googlechat Channel integration: googlechat size: S

Projects

None yet

2 participants