mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(google): bound OAuth token error response reads (#99605)
* fix(google): bound OAuth token error response reads * test(google): consolidate OAuth error cases --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -680,6 +680,17 @@ describe("loginGeminiCliOAuth", () => {
|
||||
});
|
||||
}
|
||||
|
||||
function responseTextBodyWithTextTrap(body: string, status = 500) {
|
||||
const response = new Response(body, {
|
||||
status,
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
});
|
||||
const text = vi
|
||||
.spyOn(response, "text")
|
||||
.mockRejectedValue(new Error("unexpected response.text() call"));
|
||||
return { response, text };
|
||||
}
|
||||
|
||||
function tokenResponse(): Response {
|
||||
return responseJson({
|
||||
access_token: "access-token",
|
||||
@@ -927,6 +938,30 @@ describe("loginGeminiCliOAuth", () => {
|
||||
expect(requests.filter(({ url }) => url.includes("v1internal:loadCodeAssist"))).toHaveLength(3);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
"exchange",
|
||||
"x",
|
||||
async () =>
|
||||
(await import("./oauth.token.js")).exchangeCodeForTokens("oauth-code", "pkce-verifier"),
|
||||
],
|
||||
[
|
||||
"refresh",
|
||||
"y",
|
||||
async () =>
|
||||
(await import("./oauth.token.js")).refreshTokensForGeminiCli({ refresh: "refresh-token" }),
|
||||
],
|
||||
])("bounds token %s error bodies without using response.text()", async (_flow, fill, request) => {
|
||||
const { response, text } = responseTextBodyWithTextTrap(fill.repeat(32 * 1024), 500);
|
||||
installGeminiOAuthFetchMock(() => undefined, { tokenResponse: () => response });
|
||||
|
||||
const error = await request().catch((err: unknown) => err);
|
||||
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect((error as Error).message).toBe(`Token exchange failed: ${fill.repeat(8 * 1024)}`);
|
||||
expect(text).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("falls back to GOOGLE_CLOUD_PROJECT when all loadCodeAssist endpoints fail", async () => {
|
||||
process.env.GOOGLE_CLOUD_PROJECT = "env-project";
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
asDateTimestampMs,
|
||||
resolveExpiresAtMsFromDurationSeconds,
|
||||
} from "openclaw/plugin-sdk/number-runtime";
|
||||
import { readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
||||
import { resolveOAuthClientConfig } from "./oauth.credentials.js";
|
||||
import { fetchWithTimeout } from "./oauth.http.js";
|
||||
import { resolveGoogleOAuthIdentity, resolveGooglePersonalOAuthIdentity } from "./oauth.project.js";
|
||||
@@ -10,6 +11,7 @@ import { isGeminiCliPersonalOAuth } from "./oauth.settings.js";
|
||||
import { REDIRECT_URI, TOKEN_URL, type GeminiCliOAuthCredentials } from "./oauth.shared.js";
|
||||
|
||||
const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000;
|
||||
const GOOGLE_OAUTH_TOKEN_ERROR_BODY_LIMIT_BYTES = 8 * 1024;
|
||||
|
||||
async function requestTokenGrant(body: URLSearchParams): Promise<{
|
||||
access_token?: string;
|
||||
@@ -27,7 +29,10 @@ async function requestTokenGrant(body: URLSearchParams): Promise<{
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
const errorText = await readResponseTextLimited(
|
||||
response,
|
||||
GOOGLE_OAUTH_TOKEN_ERROR_BODY_LIMIT_BYTES,
|
||||
);
|
||||
throw new Error(`Token exchange failed: ${errorText}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user