fix(core, a2a-server): prevent hang during OAuth in non-interactive sessions (#21045)

This commit is contained in:
Spencer
2026-03-04 15:35:21 -05:00
committed by GitHub
parent 29b3aa860c
commit c59ef74837
5 changed files with 335 additions and 13 deletions
+27 -1
View File
@@ -40,7 +40,10 @@ import { FORCE_ENCRYPTED_FILE_ENV_VAR } from '../mcp/token-storage/index.js';
import { GEMINI_DIR, homedir as pathsHomedir } from '../utils/paths.js';
import { debugLogger } from '../utils/debugLogger.js';
import { writeToStdout } from '../utils/stdio.js';
import { FatalCancellationError } from '../utils/errors.js';
import {
FatalCancellationError,
FatalAuthenticationError,
} from '../utils/errors.js';
import process from 'node:process';
import { coreEvents } from '../utils/events.js';
import { isHeadlessMode } from '../utils/headless.js';
@@ -107,6 +110,7 @@ const mockConfig = {
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => false,
getExperimentalZedIntegration: () => false,
isInteractive: () => true,
} as unknown as Config;
// Mock fetch globally
@@ -316,11 +320,31 @@ describe('oauth2', () => {
await eventPromise;
});
it('should throw FatalAuthenticationError in non-interactive session when manual auth is required', async () => {
const mockConfigNonInteractive = {
getNoBrowser: () => true,
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => true,
isInteractive: () => false,
} as unknown as Config;
await expect(
getOauthClient(AuthType.LOGIN_WITH_GOOGLE, mockConfigNonInteractive),
).rejects.toThrow(FatalAuthenticationError);
await expect(
getOauthClient(AuthType.LOGIN_WITH_GOOGLE, mockConfigNonInteractive),
).rejects.toThrow(
'Manual authorization is required but the current session is non-interactive.',
);
});
it('should perform login with user code', async () => {
const mockConfigWithNoBrowser = {
getNoBrowser: () => true,
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => true,
isInteractive: () => true,
} as unknown as Config;
const mockCodeVerifier = {
@@ -391,6 +415,7 @@ describe('oauth2', () => {
getNoBrowser: () => true,
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => true,
isInteractive: () => true,
} as unknown as Config;
const mockCodeVerifier = {
@@ -1171,6 +1196,7 @@ describe('oauth2', () => {
getNoBrowser: () => true,
getProxy: () => 'http://test.proxy.com:8080',
isBrowserLaunchSuppressed: () => true,
isInteractive: () => true,
} as unknown as Config;
const mockOAuth2Client = {