summaryrefslogtreecommitdiff
path: root/packages/cli
diff options
context:
space:
mode:
authorPascal Birchler <[email protected]>2025-07-09 00:10:36 +0200
committerGitHub <[email protected]>2025-07-08 22:10:36 +0000
commitc8cf954e6ef8b360b0c7880ca4d29a12eb1ec7c8 (patch)
tree55670fde25a7d59cae19d2b21ecacc67f58ae1cc /packages/cli
parent0506b40a39c04a5949c7886aaf5f87173453f0a2 (diff)
fix(auth): do not blindly default to API key auth (#3235)
Co-authored-by: matt korwel <[email protected]> Co-authored-by: N. Taylor Mullen <[email protected]>
Diffstat (limited to 'packages/cli')
-rw-r--r--packages/cli/src/gemini.tsx12
-rw-r--r--packages/cli/src/ui/components/AuthDialog.test.tsx40
-rw-r--r--packages/cli/src/ui/components/AuthDialog.tsx41
3 files changed, 69 insertions, 24 deletions
diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx
index 91425d8d..a2e14ab0 100644
--- a/packages/cli/src/gemini.tsx
+++ b/packages/cli/src/gemini.tsx
@@ -17,8 +17,8 @@ import { start_sandbox } from './utils/sandbox.js';
import {
LoadedSettings,
loadSettings,
- SettingScope,
USER_SETTINGS_PATH,
+ SettingScope,
} from './config/settings.js';
import { themeManager } from './ui/themes/theme-manager.js';
import { getStartupWarnings } from './utils/startupWarnings.js';
@@ -111,15 +111,9 @@ export async function main() {
process.exit(0);
}
- // Set a default auth type if one isn't set for a couple of known cases.
+ // Set a default auth type if one isn't set.
if (!settings.merged.selectedAuthType) {
- if (process.env.GEMINI_API_KEY) {
- settings.setValue(
- SettingScope.User,
- 'selectedAuthType',
- AuthType.USE_GEMINI,
- );
- } else if (process.env.CLOUD_SHELL === 'true') {
+ if (process.env.CLOUD_SHELL === 'true') {
settings.setValue(
SettingScope.User,
'selectedAuthType',
diff --git a/packages/cli/src/ui/components/AuthDialog.test.tsx b/packages/cli/src/ui/components/AuthDialog.test.tsx
index 8f07e2a5..60a8a930 100644
--- a/packages/cli/src/ui/components/AuthDialog.test.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.test.tsx
@@ -5,7 +5,7 @@
*/
import { render } from 'ink-testing-library';
-import { describe, it, expect, vi } from 'vitest';
+import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { AuthDialog } from './AuthDialog.js';
import { LoadedSettings, SettingScope } from '../../config/settings.js';
import { AuthType } from '@google/gemini-cli-core';
@@ -13,7 +13,21 @@ import { AuthType } from '@google/gemini-cli-core';
describe('AuthDialog', () => {
const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms));
+ let originalEnv: NodeJS.ProcessEnv;
+
+ beforeEach(() => {
+ originalEnv = { ...process.env };
+ process.env.GEMINI_API_KEY = '';
+ vi.clearAllMocks();
+ });
+
+ afterEach(() => {
+ process.env = originalEnv;
+ });
+
it('should show an error if the initial auth type is invalid', () => {
+ process.env.GEMINI_API_KEY = '';
+
const settings: LoadedSettings = new LoadedSettings(
{
settings: {
@@ -41,6 +55,30 @@ describe('AuthDialog', () => {
);
});
+ it('should detect GEMINI_API_KEY environment variable', () => {
+ process.env.GEMINI_API_KEY = 'foobar';
+
+ const settings: LoadedSettings = new LoadedSettings(
+ {
+ settings: {
+ selectedAuthType: undefined,
+ },
+ path: '',
+ },
+ {
+ settings: {},
+ path: '',
+ },
+ [],
+ );
+
+ const { lastFrame } = render(
+ <AuthDialog onSelect={() => {}} settings={settings} />,
+ );
+
+ expect(lastFrame()).toContain('Existing API key detected (GEMINI_API_KEY)');
+ });
+
it('should prevent exiting when no auth method is selected and show error message', async () => {
const onSelect = vi.fn();
const settings: LoadedSettings = new LoadedSettings(
diff --git a/packages/cli/src/ui/components/AuthDialog.tsx b/packages/cli/src/ui/components/AuthDialog.tsx
index a33e284d..d46feb0b 100644
--- a/packages/cli/src/ui/components/AuthDialog.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.tsx
@@ -24,7 +24,11 @@ export function AuthDialog({
initialErrorMessage,
}: AuthDialogProps): React.JSX.Element {
const [errorMessage, setErrorMessage] = useState<string | null>(
- initialErrorMessage || null,
+ initialErrorMessage
+ ? initialErrorMessage
+ : process.env.GEMINI_API_KEY
+ ? 'Existing API key detected (GEMINI_API_KEY). Select "Gemini API Key" option to use it.'
+ : null,
);
const items = [
{
@@ -46,13 +50,17 @@ export function AuthDialog({
{ label: 'Vertex AI', value: AuthType.USE_VERTEX_AI },
];
- let initialAuthIndex = items.findIndex(
- (item) => item.value === settings.merged.selectedAuthType,
- );
+ const initialAuthIndex = items.findIndex((item) => {
+ if (settings.merged.selectedAuthType) {
+ return item.value === settings.merged.selectedAuthType;
+ }
- if (initialAuthIndex === -1) {
- initialAuthIndex = 0;
- }
+ if (process.env.GEMINI_API_KEY) {
+ return item.value === AuthType.USE_GEMINI;
+ }
+
+ return item.value === AuthType.LOGIN_WITH_GOOGLE;
+ });
const handleAuthSelect = (authMethod: AuthType) => {
const error = validateAuthMethod(authMethod);
@@ -90,13 +98,18 @@ export function AuthDialog({
padding={1}
width="100%"
>
- <Text bold>Select Auth Method</Text>
- <RadioButtonSelect
- items={items}
- initialIndex={initialAuthIndex}
- onSelect={handleAuthSelect}
- isFocused={true}
- />
+ <Text bold>Get started</Text>
+ <Box marginTop={1}>
+ <Text>How would you like to authenticate for this project?</Text>
+ </Box>
+ <Box marginTop={1}>
+ <RadioButtonSelect
+ items={items}
+ initialIndex={initialAuthIndex}
+ onSelect={handleAuthSelect}
+ isFocused={true}
+ />
+ </Box>
{errorMessage && (
<Box marginTop={1}>
<Text color={Colors.AccentRed}>{errorMessage}</Text>