Skip to content

Commit e524878

Browse files
committed
fix(googlechat): normalize auth response headers
1 parent 7129db1 commit e524878

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ Docs: https://docs.openclaw.ai
205205
- Feishu: accept and honor `channels.feishu.blockStreaming` at the top level and per account, while keeping the legacy default off so Feishu cards no longer reject documented config or silently drop block replies. Fixes #75555. Thanks @vincentkoc.
206206
- Gateway/update: avoid `launchctl kickstart -k` immediately after fresh macOS update bootstraps, and unlink dangling global plugin-runtime symlinks during packaged postinstall and `doctor --fix` so upgrades no longer SIGTERM the newly booted Gateway or leave bundled plugin imports pointed at pruned `plugin-runtime-deps` trees. Completes #76261 and fixes #76466. (#76929)
207207
- Google Chat: normalize custom Google auth transport headers before google-auth/gaxios interceptors run, restoring webhook token verification when certificate retrieval expects Fetch `Headers`. Fixes #76742. Thanks @donbowman.
208+
- Google Chat: normalize Google auth certificate response headers before google-auth-library reads cache-control, so inbound webhook auth no longer rejects with `res?.headers.get is not a function`. Fixes #76880. Thanks @donbowman.
208209
- Doctor/plugins: reset stale `plugins.slots.memory` and `plugins.slots.contextEngine` references during `doctor --fix`, so cleanup of missing plugin config does not leave unrecoverable slot owners behind. Fixes #76550 and #76551. Thanks @vincentkoc.
209210
- Docs/WhatsApp: merge the duplicate top-level `web` objects in the gateway channel config example so copy-pasted WhatsApp config keeps both `web.whatsapp` and reconnect settings. Fixes #76619. Thanks @WadydX.
210211
- Plugins/Anthropic: expose Claude thinking profiles from the bundled provider-policy artifact so non-runtime callers keep Opus 4.7 `adaptive`, `xhigh`, and `max` instead of downgrading to `high`. Fixes #76779. Thanks @tomascupr and @iAbhi001.

extensions/googlechat/src/google-auth.runtime.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ describe("googlechat google auth runtime", () => {
348348
expect(transport.interceptors.request.add).toHaveBeenCalledWith({
349349
resolved: expect.any(Function),
350350
});
351+
expect(transport.interceptors.response.add).toHaveBeenCalledWith({
352+
resolved: expect.any(Function),
353+
});
351354
expect("window" in globalThis).toBe(false);
352355
} finally {
353356
if (originalWindowDescriptor) {
@@ -369,6 +372,20 @@ describe("googlechat google auth runtime", () => {
369372
expect(normalized.headers.get("x-test")).toBe("1");
370373
});
371374

375+
it("normalizes Google auth response headers before upstream cache-control reads", () => {
376+
const response = {
377+
data: {},
378+
headers: {
379+
"cache-control": "public, max-age=3600",
380+
},
381+
};
382+
383+
const normalized = __testing.normalizeGoogleAuthResponseHeaders(response);
384+
385+
expect(normalized.headers).toBeInstanceOf(Headers);
386+
expect(normalized.headers.get("cache-control")).toBe("public, max-age=3600");
387+
});
388+
372389
it("rejects service-account credentials that override Google auth endpoints", async () => {
373390
await expect(
374391
resolveValidatedGoogleChatCredentials({

extensions/googlechat/src/google-auth.runtime.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ type GoogleAuthTransport = InstanceType<GaxiosModule["Gaxios"]>;
2323
type GoogleAuthRequestWithUnknownHeaders = RequestInit & {
2424
headers?: unknown;
2525
};
26+
type GoogleAuthResponseWithUnknownHeaders = {
27+
headers?: unknown;
28+
};
2629
type GuardedGoogleAuthRequestInit = RequestInit & {
2730
agent?: unknown;
2831
cert?: unknown;
@@ -79,12 +82,24 @@ function normalizeGoogleAuthPreparedRequestHeaders<T extends GoogleAuthRequestWi
7982
return config as T & { headers: Headers };
8083
}
8184

85+
function normalizeGoogleAuthResponseHeaders<T extends GoogleAuthResponseWithUnknownHeaders>(
86+
response: T,
87+
): T & { headers: Headers } {
88+
if (!(response.headers instanceof Headers)) {
89+
response.headers = new Headers(response.headers as HeadersInit | undefined);
90+
}
91+
return response as T & { headers: Headers };
92+
}
93+
8294
function installGoogleAuthHeaderCompatibilityInterceptor(
8395
transport: GoogleAuthTransport,
8496
): GoogleAuthTransport {
8597
transport.interceptors.request.add({
8698
resolved: async (config) => normalizeGoogleAuthPreparedRequestHeaders(config),
8799
});
100+
transport.interceptors.response.add({
101+
resolved: async (response) => normalizeGoogleAuthResponseHeaders(response),
102+
});
88103
return transport;
89104
}
90105

@@ -558,6 +573,7 @@ export const __testing = {
558573
googleAuthTransportPromise = null;
559574
},
560575
normalizeGoogleAuthPreparedRequestHeaders,
576+
normalizeGoogleAuthResponseHeaders,
561577
resolveGoogleAuthEnvProxyUrl,
562578
validateGoogleChatServiceAccountCredentials,
563579
};

0 commit comments

Comments
 (0)