Skip to content

Commit 5165ddc

Browse files
authored
Merge 122b2c7 into 219f27a
2 parents 219f27a + 122b2c7 commit 5165ddc

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

extensions/google/oauth.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,17 @@ describe("loginGeminiCliOAuth", () => {
680680
});
681681
}
682682

683+
function responseTextBodyWithTextTrap(body: string, status = 500) {
684+
const response = new Response(body, {
685+
status,
686+
headers: { "Content-Type": "text/plain" },
687+
});
688+
const text = vi
689+
.spyOn(response, "text")
690+
.mockRejectedValue(new Error("unexpected response.text() call"));
691+
return { response, text };
692+
}
693+
683694
function tokenResponse(): Response {
684695
return responseJson({
685696
access_token: "access-token",
@@ -927,6 +938,30 @@ describe("loginGeminiCliOAuth", () => {
927938
expect(requests.filter(({ url }) => url.includes("v1internal:loadCodeAssist"))).toHaveLength(3);
928939
});
929940

941+
it.each([
942+
[
943+
"exchange",
944+
"x",
945+
async () =>
946+
(await import("./oauth.token.js")).exchangeCodeForTokens("oauth-code", "pkce-verifier"),
947+
],
948+
[
949+
"refresh",
950+
"y",
951+
async () =>
952+
(await import("./oauth.token.js")).refreshTokensForGeminiCli({ refresh: "refresh-token" }),
953+
],
954+
])("bounds token %s error bodies without using response.text()", async (_flow, fill, request) => {
955+
const { response, text } = responseTextBodyWithTextTrap(fill.repeat(32 * 1024), 500);
956+
installGeminiOAuthFetchMock(() => undefined, { tokenResponse: () => response });
957+
958+
const error = await request().catch((err: unknown) => err);
959+
960+
expect(error).toBeInstanceOf(Error);
961+
expect((error as Error).message).toBe(`Token exchange failed: ${fill.repeat(8 * 1024)}`);
962+
expect(text).not.toHaveBeenCalled();
963+
});
964+
930965
it("falls back to GOOGLE_CLOUD_PROJECT when all loadCodeAssist endpoints fail", async () => {
931966
process.env.GOOGLE_CLOUD_PROJECT = "env-project";
932967

extensions/google/oauth.token.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import {
33
asDateTimestampMs,
44
resolveExpiresAtMsFromDurationSeconds,
55
} from "openclaw/plugin-sdk/number-runtime";
6+
import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
67
import { resolveOAuthClientConfig } from "./oauth.credentials.js";
78
import { fetchWithTimeout } from "./oauth.http.js";
89
import { resolveGoogleOAuthIdentity, resolveGooglePersonalOAuthIdentity } from "./oauth.project.js";
910
import { isGeminiCliPersonalOAuth } from "./oauth.settings.js";
1011
import { REDIRECT_URI, TOKEN_URL, type GeminiCliOAuthCredentials } from "./oauth.shared.js";
1112

1213
const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000;
14+
const GOOGLE_OAUTH_TOKEN_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
1315

1416
async function requestTokenGrant(body: URLSearchParams): Promise<{
1517
access_token?: string;
@@ -27,7 +29,10 @@ async function requestTokenGrant(body: URLSearchParams): Promise<{
2729
});
2830

2931
if (!response.ok) {
30-
const errorText = await response.text();
32+
const errorText = await readResponseTextLimited(
33+
response,
34+
GOOGLE_OAUTH_TOKEN_ERROR_BODY_LIMIT_BYTES,
35+
);
3136
throw new Error(`Token exchange failed: ${errorText}`);
3237
}
3338

0 commit comments

Comments
 (0)