fix: GCA creds loading order (#6498)
This commit is contained in:
parent
3960ccf781
commit
5fe4e02310
|
@ -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', () => {
|
describe('with GCP environment variables', () => {
|
||||||
it('should use GOOGLE_CLOUD_ACCESS_TOKEN when GOOGLE_GENAI_USE_GCA is true', async () => {
|
it('should use GOOGLE_CLOUD_ACCESS_TOKEN when GOOGLE_GENAI_USE_GCA is true', async () => {
|
||||||
vi.stubEnv('GOOGLE_GENAI_USE_GCA', 'true');
|
vi.stubEnv('GOOGLE_GENAI_USE_GCA', 'true');
|
||||||
|
|
|
@ -351,27 +351,32 @@ export function getAvailablePort(): Promise<number> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> {
|
async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> {
|
||||||
try {
|
const pathsToTry = [
|
||||||
const keyFile =
|
getCachedCredentialPath(),
|
||||||
process.env['GOOGLE_APPLICATION_CREDENTIALS'] ||
|
process.env['GOOGLE_APPLICATION_CREDENTIALS'],
|
||||||
getCachedCredentialPath();
|
].filter((p): p is string => !!p);
|
||||||
|
|
||||||
const creds = await fs.readFile(keyFile, 'utf-8');
|
for (const keyFile of pathsToTry) {
|
||||||
client.setCredentials(JSON.parse(creds));
|
try {
|
||||||
|
const creds = await fs.readFile(keyFile, 'utf-8');
|
||||||
|
client.setCredentials(JSON.parse(creds));
|
||||||
|
|
||||||
// This will verify locally that the credentials look good.
|
// This will verify locally that the credentials look good.
|
||||||
const { token } = await client.getAccessToken();
|
const { token } = await client.getAccessToken();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return false;
|
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) {
|
async function cacheCredentials(credentials: Credentials) {
|
||||||
|
|
Loading…
Reference in New Issue