1jehuang / 1jehuang/jcode

Gemini API key incorrectly marks Google Gemini OAuth as configured

Open
#968 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Summary

When GEMINI_API_KEY is configured but Gemini OAuth credentials are absent, the provider setup/login picker marks both Google Gemini (OAuth) and Gemini API (API key) as configured.

Logging out of Google Gemini OAuth successfully removes ~/.jcode/gemini_oauth.json, but the OAuth row remains configured as long as GEMINI_API_KEY is present. This makes it impossible to tell from the UI whether Code Assist OAuth is actually active, which matters because OAuth and Gemini Developer API access have different endpoints and terms.

Environment

  • Jcode: v0.76.0 (bbef1f6a8)
  • OS: Windows x86_64
  • Also reproduces in current master source at 8fc780b

Reproduction

  1. Configure GEMINI_API_KEY.
  2. Ensure native Gemini OAuth is absent:
    • ~/.jcode/gemini_oauth.json does not exist.
    • No trusted external Gemini OAuth source is enabled.
  3. Open the provider setup picker.
  4. Observe the rows for Google Gemini and Gemini API.

Alternative reproduction:

  1. Configure both Gemini OAuth and GEMINI_API_KEY.
  2. Log out of Google Gemini from Jcode.
  3. Reopen the provider setup picker.

Actual behavior

  • Google Gemini | OAuth | configured
  • Gemini API | API key | configured
  • jcode auth status --json reports the Gemini OAuth provider as available even though its credential source is none.

The OAuth logout itself succeeds and removes ~/.jcode/gemini_oauth.json.

Expected behavior

With only GEMINI_API_KEY configured:

  • Google Gemini | OAuth | setup
  • Gemini API | API key | configured

With only OAuth configured, the inverse should be shown. With both configured, both rows should be configured.

Root cause

crates/jcode-base/src/auth/mod.rs, in build_auth_status_uncached, combines the two authentication methods:

status.gemini = if gemini::has_api_key() {
    AuthState::Available
} else {
    token_state(gemini::load_tokens().map(|tokens| tokens.is_expired()))
};

The OAuth descriptor in crates/jcode-provider-metadata/src/catalog.rs uses that combined state:

pub const GEMINI_LOGIN_PROVIDER: LoginProviderDescriptor = LoginProviderDescriptor {
    id: "gemini",
    display_name: "Google Gemini",
    auth_kind: LoginProviderAuthKind::OAuth,
    auth_state_key: LoginProviderAuthStateKey::Gemini,
    // ...
};

A separate GEMINI_API_LOGIN_PROVIDER already exists and checks the gemini-api OpenAI-compatible profile, so an API key can independently make that row configured.

Suggested fix

Keep provider runtime credential resolution separate from login-method status. The provider setup/account surfaces need method-specific state:

  • Gemini OAuth state should be derived only from trusted OAuth tokens.
  • Gemini API state should be derived only from GEMINI_API_KEY / the gemini-api profile.
  • If the native Gemini runtime intentionally supports both methods, split the status fields/keys, for example GeminiOauth and GeminiApiKey, rather than using a combined state for the OAuth descriptor.

Regression tests

Cover all four combinations in the provider assessment/picker:

  1. Neither configured: both rows show setup.
  2. OAuth only: OAuth configured, API setup.
  3. API key only: OAuth setup, API configured.
  4. Both configured: both rows configured.

Also verify that logging out of OAuth while retaining GEMINI_API_KEY changes only the OAuth row to setup and does not remove or disable the API key.

Policy-sensitive distinction

This is more than a cosmetic status-label issue. Google's current Antigravity Terms of Service explicitly state that using third-party software, tools, or services to access Antigravity, for example OpenClaw with Antigravity OAuth, is a breach that may result in account suspension or termination. The Antigravity FAQ likewise explains why third-party tools such as Claude Code, OpenClaw, and OpenCode cannot use an Antigravity login:

This report is not requesting removal of the OAuth provider. Removing, deprecating, or relabeling it in light of the current Antigravity CLI/IDE policy is a separate product decision. However, Jcode should accurately distinguish the Google OAuth/Code Assist path from the sanctioned Gemini Developer API-key path so users can verify which credential and endpoint are configured and active. Maintainers may also want to confirm whether the exposed OAuth integration remains intended under the current Antigravity terms.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in crates/jcode-base/src/auth/mod.rs and inspect build_auth_status_uncached, then compare its Gemini state with the descriptors in crates/jcode-provider-metadata/src/catalog.rs. Trace the provider assessment and picker status, and add regression coverage for neither, OAuth-only, API-key-only, and both configured. Done means OAuth logout changes only the OAuth row to setup while the API row remains configured.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, authentication, cli, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.