Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@galz10
Copy link
Collaborator

@galz10 galz10 commented Oct 22, 2025

TLDR

This PR improves the authentication flow for Gemini API keys. It introduces a new dialog for API key input, securely stores the key, and refactors the related code for better maintainability.

Dive Deeper

The main changes in this PR are:

  1. New ApiAuthDialog: A new React component ApiAuthDialog is created to prompt the user for their Gemini API key. This provides a better user experience than relying on environment variables.
  2. ApiKeyCredentialStorage: A new class ApiKeyCredentialStorage is added to securely store the API key in the system's keychain. This avoids having to re-enter the key on every run.
  3. Refactored useAuth hook: The useAuth hook is refactored to handle the new API key input flow. The logic for loading the API key is centralized in the reloadApiKey function.
  4. Controlled TextInput component: The TextInput component is refactored to be a fully controlled component, which simplifies its implementation and makes it more reusable.
  5. Configuration updates: The configuration loading logic is updated to read the API key from the new ApiKeyCredentialStorage.

Reviewer Test Plan

  1. Run the Gemini CLI without any authentication configured.

  2. Select "Gemini API Key" as the authentication method.

  3. You should be prompted to enter your API key in a new dialog.

  4. Enter a valid API key. The CLI should authenticate successfully.

  5. To test the clearing of the key, you can manually delete the entry from your keychain (service name: gemini-cli-api-key) and rerun the CLI. You should be prompted for the key again.

  6. Unset GEMINI_API_KEY environent variable

  7. Run the Gemini CLI with "Gemini API Key" authentication configured.

  8. You should be prompted to enter your API key in a new dialog.

  9. Enter a valid API key. The CLI should authenticate successfully.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

No linked issues

   This commit introduces a series of improvements to the API key authentication
   process.

   These changes result in a more robust and user-friendly authentication
   experience when using a Gemini API key.
@galz10 galz10 requested a review from a team as a code owner October 22, 2025 22:37
@galz10 galz10 linked an issue Oct 22, 2025 that may be closed by this pull request
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @galz10, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the user experience for Gemini API key authentication within the CLI. It introduces a dedicated interactive dialog for API key input and ensures secure storage of these keys in the system's keychain. This change centralizes API key management, reduces friction for repeated use, and refactors underlying authentication mechanisms for improved maintainability and robustness.

Highlights

  • Improved API Key Authentication: Introduced a new ApiAuthDialog component for a dedicated and user-friendly input experience for Gemini API keys, moving away from sole reliance on environment variables.
  • Secure API Key Storage: Implemented ApiKeyCredentialStorage to securely store API keys in the system's keychain, eliminating the need for users to re-enter their key on every run.
  • Refactored Authentication Logic: The useAuth hook has been refactored to seamlessly integrate the new API key input and storage flow, centralizing key loading logic in a new reloadApiKey function.
  • Controlled TextInput Component: The TextInput component was refactored into a fully controlled component, enhancing its reusability and simplifying its implementation across the UI.
  • Configuration Updates: The core configuration logic now reads API keys from the new ApiKeyCredentialStorage, ensuring consistency with the updated authentication flow.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@galz10 galz10 linked an issue Oct 22, 2025 that may be closed by this pull request
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR introduces a new, improved authentication flow for Gemini API keys, featuring a dedicated input dialog and secure keychain storage. The refactoring enhances maintainability and user experience. However, I've identified a few high-severity issues that should be addressed. The API key input is not masked, which is a security concern. There's an inconsistency in API key source precedence between different parts of the code, which could lead to unexpected behavior. Finally, there's no validation for empty API key submissions, potentially leaving the application in a broken state. Fixing these issues will make the new authentication flow more robust and secure.

Comment on lines 406 to 417
async (apiKey: string) => {
try {
await ApiKeyCredentialStorage.saveApiKey(apiKey);
await reloadApiKey();
await config.refreshAuth(AuthType.USE_GEMINI);
setAuthState(AuthState.Authenticated);
} catch (e) {
onAuthError(
`Failed to save API key: ${e instanceof Error ? e.message : String(e)}`,
);
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The handleApiKeySubmit function does not validate if the submitted API key is empty or contains only whitespace. Submitting an empty key will cause ApiKeyCredentialStorage.saveApiKey to delete any existing key, and the subsequent authentication will likely fail silently or with a confusing error, leaving the application in a broken state where it appears authenticated but has no valid key. You should add a check at the beginning of handleApiKeySubmit to ensure the key is not empty and use onAuthError to display a message to the user if it is.

    async (apiKey: string) => {
      if (!apiKey.trim()) {
        onAuthError('API key cannot be empty.');
        return;
      }
      try {
        await ApiKeyCredentialStorage.saveApiKey(apiKey);
        await reloadApiKey();
        await config.refreshAuth(AuthType.USE_GEMINI);
        setAuthState(AuthState.Authenticated);
      } catch (e) {
        onAuthError(
          `Failed to save API key: ${e instanceof Error ? e.message : String(e)}`,
        );
      }
    },

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do this, but since we are using keychain, i think it makes sense that if the api key is an empty string, then we clear the api key, i'll add a check to see if the user just enters a bunch of white spaces then we should raise this error.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree it is worth it. it is odd I can submit the dialog when the apikey is empty. i should have to press escape and I should get an error message explaining why submit was blocked.

@github-actions
Copy link

github-actions bot commented Oct 22, 2025

Size Change: +9.93 kB (+0.05%)

Total Size: 20.3 MB

Filename Size Change
./bundle/gemini.js 20.2 MB +9.93 kB (+0.05%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-closed.sb 1.03 kB
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-closed.sb 3.29 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB

compressed-size-action

try {
await this.storage.deleteCredentials(DEFAULT_API_KEY_ENTRY);
} catch (error: unknown) {
console.error('Failed to clear API key from storage:', error);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to log and throw

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like logging to the debugLogger might be helpful

}

// Normal character input
if (key.sequence && !key.ctrl && !key.meta) {
Copy link
Collaborator

@jacob314 jacob314 Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are letting a lot of unsafe chars in. examples: tabs, up arrow, down arrow. UI does really weird things due to this if you press up or down arrows.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing happens if you press up, down, tab

Copy link
Collaborator

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other issue noticed manually testing:
ctrl-c now doesn't seem to work in the api key dialog or the auth dialog. odd that changed as they do work in that dialog on the public build.

  This commit refactors the TextInput component to be a controlled component that uses the useTextBuffer hook to manage its state.
  This change simplifies the TextInput component and makes it more reusable.

  The ApiAuthDialog has been updated to use the new TextInput component.

  Additionally, the AP key resolution logic has been updated to prioritize the stored API key over the GEMINI_API_KEY
  environment variable.
@galz10 galz10 requested a review from jacob314 October 27, 2025 20:58
useTextBuffer({
viewport,
isValidPath: () => false,
inputFilter: (text) => text.replace(/[^0-9]/g, ''),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it might make sense to also apply the inputFilter to the initial value passed in but not sure that is a good idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so inputFilter is optional, we can apply it but it might be overkill, i think the idea is that whatever is in intitialValue will be valid

Copy link
Collaborator

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything works well now when I manually test it. Did one final round of review comments then approved.

Copy link
Collaborator

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@galz10 galz10 enabled auto-merge October 28, 2025 21:18
@galz10 galz10 disabled auto-merge October 30, 2025 00:10
@galz10 galz10 added this pull request to the merge queue Oct 30, 2025
Merged via the queue into main with commit 06035d5 Oct 30, 2025
22 checks passed
@galz10 galz10 deleted the galzahavi/add/interactive-prompt branch October 30, 2025 01:59
thacio added a commit to thacio/auditaria that referenced this pull request Oct 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(auth): Add option to save GEMINI_API_KEY to .env file feat(auth): Add interactive prompt for GEMINI_API_KEY

2 participants