fix: GCA creds loading order (#6498)

This commit is contained in:
Gaurav 2025-08-18 14:11:19 -07:00 committed by GitHub
parent 3960ccf781
commit 5fe4e02310
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 86 additions and 17 deletions

View File

@ -324,6 +324,70 @@ describe('oauth2', () => {
});
});
describe('credential loading order', () => {
it('should prioritize default cached credentials over GOOGLE_APPLICATION_CREDENTIALS', async () => {
// Setup default cached credentials
const defaultCreds = { refresh_token: 'default-cached-token' };
const defaultCredsPath = path.join(
tempHomeDir,
'.gemini',
'oauth_creds.json',
);
await fs.promises.mkdir(path.dirname(defaultCredsPath), {
recursive: true,
});
await fs.promises.writeFile(
defaultCredsPath,
JSON.stringify(defaultCreds),
);
// Setup credentials via environment variable
const envCreds = { refresh_token: 'env-var-token' };
const envCredsPath = path.join(tempHomeDir, 'env_creds.json');
await fs.promises.writeFile(envCredsPath, JSON.stringify(envCreds));
vi.stubEnv('GOOGLE_APPLICATION_CREDENTIALS', envCredsPath);
const mockClient = {
setCredentials: vi.fn(),
getAccessToken: vi.fn().mockResolvedValue({ token: 'test-token' }),
getTokenInfo: vi.fn().mockResolvedValue({}),
on: vi.fn(),
};
(OAuth2Client as unknown as Mock).mockImplementation(
() => mockClient as unknown as OAuth2Client,
);
await getOauthClient(AuthType.LOGIN_WITH_GOOGLE, mockConfig);
// Assert the correct credentials were used
expect(mockClient.setCredentials).toHaveBeenCalledWith(defaultCreds);
expect(mockClient.setCredentials).not.toHaveBeenCalledWith(envCreds);
});
it('should fall back to GOOGLE_APPLICATION_CREDENTIALS if default cache is missing', async () => {
// Setup credentials via environment variable
const envCreds = { refresh_token: 'env-var-token' };
const envCredsPath = path.join(tempHomeDir, 'env_creds.json');
await fs.promises.writeFile(envCredsPath, JSON.stringify(envCreds));
vi.stubEnv('GOOGLE_APPLICATION_CREDENTIALS', envCredsPath);
const mockClient = {
setCredentials: vi.fn(),
getAccessToken: vi.fn().mockResolvedValue({ token: 'test-token' }),
getTokenInfo: vi.fn().mockResolvedValue({}),
on: vi.fn(),
};
(OAuth2Client as unknown as Mock).mockImplementation(
() => mockClient as unknown as OAuth2Client,
);
await getOauthClient(AuthType.LOGIN_WITH_GOOGLE, mockConfig);
// Assert the correct credentials were used
expect(mockClient.setCredentials).toHaveBeenCalledWith(envCreds);
});
});
describe('with GCP environment variables', () => {
it('should use GOOGLE_CLOUD_ACCESS_TOKEN when GOOGLE_GENAI_USE_GCA is true', async () => {
vi.stubEnv('GOOGLE_GENAI_USE_GCA', 'true');

View File

@ -351,27 +351,32 @@ export function getAvailablePort(): Promise<number> {
}
async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> {
try {
const keyFile =
process.env['GOOGLE_APPLICATION_CREDENTIALS'] ||
getCachedCredentialPath();
const pathsToTry = [
getCachedCredentialPath(),
process.env['GOOGLE_APPLICATION_CREDENTIALS'],
].filter((p): p is string => !!p);
const creds = await fs.readFile(keyFile, 'utf-8');
client.setCredentials(JSON.parse(creds));
for (const keyFile of pathsToTry) {
try {
const creds = await fs.readFile(keyFile, 'utf-8');
client.setCredentials(JSON.parse(creds));
// This will verify locally that the credentials look good.
const { token } = await client.getAccessToken();
if (!token) {
return false;
// This will verify locally that the credentials look good.
const { token } = await client.getAccessToken();
if (!token) {
continue;
}
// This will check with the server to see if it hasn't been revoked.
await client.getTokenInfo(token);
return true;
} catch (_) {
// Ignore and try next path.
}
// This will check with the server to see if it hasn't been revoked.
await client.getTokenInfo(token);
return true;
} catch (_) {
return false;
}
return false;
}
async function cacheCredentials(credentials: Credentials) {