Skip to content

fix(oauth): stop OAuth login from deleting a stored provider API key#491

Open
wonsh42 wants to merge 3 commits into
lidge-jun:devfrom
wonsh42:fix/oauth-login-preserves-api-key
Open

fix(oauth): stop OAuth login from deleting a stored provider API key#491
wonsh42 wants to merge 3 commits into
lidge-jun:devfrom
wonsh42:fix/oauth-login-preserves-api-key

Conversation

@wonsh42

@wonsh42 wonsh42 commented Jul 26, 2026

Copy link
Copy Markdown

Summary

upsertOAuthProvider replaced a provider's config entry with the bare preset on every OAuth login:

config.providers[provider] = { ...def.providerConfig };

For providers that can be billed either way — registry entries with allowKeyAuthOverride (xai, github-copilot) — this deleted apiKey and apiKeyPool from config.json and silently flipped an explicit authMode: "key" billing choice back to the subscription. The stored key was gone and had to be pasted again, with no message saying so.

router.ts already honors authMode: "key" for exactly these providers, so the two credentials are meant to coexist. This makes the write path agree with the routing path.

Change

Carry apiKey / apiKeyPool over, and keep an explicitly chosen authMode: "key", so logging in never changes which credential bills the request. OAuth-only providers and fresh logins still get the untouched preset — only allowKeyAuthOverride entries with an existing config are treated specially.

Testing

New tests/oauth-upsert-preserves-api-key.test.ts, 5 cases:

  • xai: stored key, pool, and authMode: "key" all survive a login
  • github-copilot: same preservation
  • key carried over but authMode: "oauth" untouched when the user did not pick key billing
  • oauth-only provider (anthropic) still gets the plain preset, stale user fields dropped
  • fresh login on an unconfigured provider gets the untouched preset

Ran locally against this branch:

  • bun test tests/oauth-upsert-preserves-api-key.test.ts — 5 pass
  • bun test on the adjacent OAuth/key suites (oauth-provider-reconcile, oauth-accounts-api, provider-api-keys, oauth-public-surface, xai-oauth-retry, github-copilot-oauth) — 32 pass, 0 fail
  • bun x tsc --noEmit — clean
  • bun scripts/privacy-scan.ts — passed

Not run: the full bun scripts/test.ts suite.

Notes

I hit this while looking into a report that Claude's API key and OAuth login could not be signed in at the same time. anthropic is not an allowKeyAuthOverride entry, so that case is separate — the dedicated anthropic-apikey registry entry already covers it, and this PR does not touch that. This fix is only about the key-deleting write path on the providers where both credentials are supported.

Summary by CodeRabbit

  • Bug Fixes
    • OAuth sign-ins now preserve existing API keys and key-based authentication settings for supported providers.
    • OAuth-only providers apply the correct OAuth preset and no longer retain key credentials.
    • When stored keys are missing or invalid, the provider configuration falls back appropriately.
  • Tests
    • Added regression coverage for credential preservation, sanitization/cleanup, and correct auth-mode transitions during OAuth provider upserts.
  • Chores
    • Updated the package version to 2.7.40.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2b7c5ec9-a01c-4991-b129-9650742f7838

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

upsertOAuthProvider now preserves sanitized key credentials for registry-approved providers, retains key mode when appropriate, and applies OAuth presets otherwise. Regression tests cover credential filtering, provider modes, key removal, and fresh logins. The package version is updated to 2.7.40.

Changes

OAuth credential preservation

Layer / File(s) Summary
Preserve credentials during OAuth upsert
src/oauth/index.ts, tests/oauth-upsert-preserves-api-key.test.ts
upsertOAuthProvider uses the provider registry to preserve valid apiKey and apiKeyPool values for eligible providers, sanitizes malformed or unsafe entries, retains key mode when applicable, and applies plain OAuth presets for other providers. Regression tests cover supported providers, mode transitions, key removal, and fresh logins.

Release version

Layer / File(s) Summary
Bump package version
package.json
The package version changes from 2.7.35 to 2.7.40.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: OAuth login no longer deletes stored provider API keys.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

Target branch corrected

This pull request now targets dev.

The [WRONG BRANCH] title prefix has been removed. The pull request has been marked ready for review again.

@github-actions github-actions Bot changed the title fix(oauth): stop OAuth login from deleting a stored provider API key [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@github-actions github-actions Bot added the bug Something isn't working label Jul 26, 2026
@wonsh42 wonsh42 changed the title [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@github-actions github-actions Bot changed the title fix(oauth): stop OAuth login from deleting a stored provider API key [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@wonsh42
wonsh42 marked this pull request as ready for review July 26, 2026 07:26
@wonsh42

wonsh42 commented Jul 26, 2026

Copy link
Copy Markdown
Author

@lidge-jun 수정해주삼

@wonsh42 wonsh42 changed the title [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@github-actions github-actions Bot changed the title fix(oauth): stop OAuth login from deleting a stored provider API key [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@lidge-jun

Copy link
Copy Markdown
Owner

ㄱㄷㄱㄷ 지금 클로드 데스크탑이랑 그록 작업중

coderabbitai[bot]

This comment was marked as resolved.

@wonsh42

wonsh42 commented Jul 26, 2026

Copy link
Copy Markdown
Author

ㄱㄷㄱㄷ 지금 클로드 데스크탑이랑 그록 작업중

ㄳㄳ 나 또 버그(?) 발견했는데 수정해서 pr 올려드림

@wonsh42

wonsh42 commented Jul 26, 2026

Copy link
Copy Markdown
Author

ㄱㄷㄱㄷ 지금 클로드 데스크탑이랑 그록 작업중

클로드 데스크톱도 되게 할꺼임? cli만 돼서 불편하던데 (내가 기능을 못찾았던건가?)
ssh 잘되게좀 만들어줘요

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@wonsh42 wonsh42 changed the title [WRONG BRANCH] fix(oauth): stop OAuth login from deleting a stored provider API key fix(oauth): stop OAuth login from deleting a stored provider API key Jul 26, 2026
@wonsh42
wonsh42 force-pushed the fix/oauth-login-preserves-api-key branch from 8eca4eb to 73aa7f2 Compare July 26, 2026 08:48
@wonsh42
wonsh42 changed the base branch from main to dev July 26, 2026 08:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/oauth/index.ts (1)

618-631: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve key mode when authMode is omitted

src/providers/api-keys.ts never writes authMode for API-key providers, so persisted xai/github-copilot entries can legitimately have an undefined mode. In src/oauth/index.ts:628-629, the strict existing.authMode === "key" check then skips restoration and the provider falls back to the OAuth preset, even though a valid apiKey/apiKeyPool is present.

Treat an omitted authMode as key-mode here, e.g. restore "key" when storedApiKey exists and existing.authMode is either "key" or undefined.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oauth/index.ts` around lines 618 - 631, The key-mode restoration in
upsertOAuthProvider currently requires existing.authMode to equal "key", so
persisted API-key providers with an omitted mode lose their key authentication.
Update the condition in upsertOAuthProvider to set next.authMode to "key" when
storedApiKey exists and existing.authMode is either "key" or undefined, while
preserving other provider behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/oauth/index.ts`:
- Around line 618-631: The key-mode restoration in upsertOAuthProvider currently
requires existing.authMode to equal "key", so persisted API-key providers with
an omitted mode lose their key authentication. Update the condition in
upsertOAuthProvider to set next.authMode to "key" when storedApiKey exists and
existing.authMode is either "key" or undefined, while preserving other provider
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e42901d8-dbc9-4d27-a5d7-3748cd2e5e89

📥 Commits

Reviewing files that changed from the base of the PR and between 73aa7f2 and e0debe2.

📒 Files selected for processing (2)
  • src/oauth/index.ts
  • tests/oauth-upsert-preserves-api-key.test.ts

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict

Request changes — do not merge until the PR is rebased/merged onto current dev and the package.json conflict is resolved without regressing the published version. Optional follow-ups are not accepted for this PR; all quality items below must ship in this PR before merge.

Summary

Target branch is correctly dev. The OAuth upsert fix itself is sound and well-tested: for allowKeyAuthOverride providers (xai, github-copilot), upsertOAuthProvider now preserves sanitized apiKey / apiKeyPool and keeps an explicit authMode: "key" only while a valid active key remains, matching router.ts's authMode === "key" gate. The follow-up commit correctly restores OAuth mode after final key removal. GitHub currently reports mergeable: CONFLICTING, mergeStateStatus: DIRTY.

Blocking findings

  1. Merge conflict against current dev (mergeable=CONFLICTING, mergeStateStatus=DIRTY).
    • Conflicted file (verified via local merge of e0debe22 into dev @ 58f0fab): package.json only.
    • Conflict hunk:
      • dev: "version": "2.7.41"
      • this PR: "version": "2.7.40"
    • src/oauth/index.ts and tests/oauth-upsert-preserves-api-key.test.ts apply cleanly.
    • Required: rebase or merge latest dev into this branch and resolve in this PR before merge. When resolving, keep 2.7.41 (current dev) — do not downgrade to 2.7.40. Prefer dropping the release: v2.7.40 / version-bump commit from this bugfix entirely; version bumps belong to maintainer release promotion, not a contributor OAuth fix.

Additional required quality changes (fix in this PR before merge)

  1. Drop / neutralize the version bump. The three-dot diff still changes package.json 2.7.35 → 2.7.40 via commit 66de25ad (release: v2.7.40). That is out of scope for this fix and is what conflicts with dev's 2.7.41. Resolve by taking dev's version (no version change in this PR).
  2. Re-run full CI on the rebased tip. Latest Cross-platform CI for e0debe22 is action_required (fork PR), not a green suite on the current tip. After rebase/conflict resolution, ensure Cross-platform CI / typecheck / tests pass on the mergeable SHA (earlier success on 8eca4eb does not cover the follow-up commit + rebase).
  3. Omitted authMode with a stored key (CodeRabbit / related). src/oauth/index.ts:629 only restores authMode: "key" when existing.authMode === "key". Fix in this PR so a preserved/sanitized active key (or equivalent key material that should keep key billing) also results in explicit authMode: "key" when mode was omitted, and align with router.ts / account semantics as needed so key override is not lost. Cover with a focused regression test.
  4. Unsafe active key + valid pool alternate (tests/... "rejects an unsafe active key…"): today this drops the active key, keeps the pool, and falls back to oauth. In this PR, promote the first safe pool entry into apiKey and keep key mode when a valid pool alternate exists (instead of falling back to oauth while pool keys remain usable).
  5. Share / reuse sanitization helpers with src/providers/api-keys.ts CRLF/trim checks where practical on this write path, rather than leaving a parallel defensive copy as follow-up polish.

Optional / non-blocking

None. Do not defer quality work to a follow-up PR; ship the items above in this PR.

Standards / Spec / Security

  • Standards: Focused Bun-native change with a dedicated regression suite adjacent to the OAuth/key surface. Hard violation: shipping a release version bump inside a bug-fix PR (and conflict-regressing 2.7.41 → 2.7.40). No Node-only APIs introduced.
  • Spec: Matches the PR-stated bug (OAuth login must not delete stored keys / flip explicit key billing for allowKeyAuthOverride providers). OAuth-only providers still get a plain preset overwrite. No linked GitHub issue; PR body is the effective spec — implementation aligns. No docs change needed for this internal write-path fix.
  • Security / privacy: Credential fields are sanitized (reject non-strings / blank / CRLF) before write-back; no request-body or key logging added. Touches OAuth config write path — worth a maintainer glance, but not a token-exfiltration or workflow-permission concern.

CI / process gates

Gate Status
Base branch dev (correct; wrong-branch enforcer already corrected earlier)
mergeable / mergeStateStatus CONFLICTING / DIRTY — blocking
Conflicted files package.json
Cross-platform CI (tip e0debe22) action_required (needs fork approval / not green on tip)
Enforce PR target / label / CodeRabbit pass
Prior full CI success 8eca4eb only (pre follow-up)

Event: request-changes

After fixes

Once all blocking + required quality changes above are addressed (and conflicts/rebase done), mark this PR Ready for review (leave draft only until then). Then ping for re-review / CI.

@Wibias
Wibias marked this pull request as draft July 26, 2026 20:18
lidge-jun added a commit that referenced this pull request Jul 27, 2026
Two read-only audit lenses returned 30 contradictions; the verified ones are
applied here and recorded in 006_corrections.md.

Factual corrections:
- claude-code#1124 closed 2025-05-16, not 2025-08-10
- 13 open enhancement issues, not 11
- #529 is merged, so issue #42 phase 2 is done
- #418 has no PR behind it; it was miscounted as in-flight
- #528 does not contain #424's current head, so it needs a rebase
- #527's retarget is manual and independent of #526

Framing corrections:
- stale-needs-info.yml is absent from the default branch, so bundle C had no
  real deadline
- the debug switch #543's reporter asked for already exists
- whether #545 is our defect is answerable from code, not owner judgment
- #491 is an OAuth credential change, so it is a security boundary rather
  than a warm-up; #533 and #447 keep their security classification too

Structure: bundle G added for roadmap honesty, bundle F rescoped to the
security boundary, #498 split out of bundle B, cycle order rebuilt, and the
loop archetype corrected to decision-elicitation.
wonsh42 and others added 3 commits July 27, 2026 19:47
`upsertOAuthProvider` replaced the provider entry with the bare preset on
every OAuth login. For providers that can be billed either way
(`allowKeyAuthOverride`: xai, github-copilot) this deleted `apiKey` and
`apiKeyPool` from config.json and silently flipped an explicit
`authMode: "key"` billing choice back to the subscription — the key was gone
and had to be pasted again.

Carry the key fields over and keep an explicitly chosen `authMode: "key"`,
so logging in never changes which credential bills the request. OAuth-only
providers and fresh logins still get the untouched preset.
…omitted

Address review follow-ups so OAuth login preserves key billing when a usable key remains, including pool promotion and shared API-key sanitization.
@Wibias
Wibias force-pushed the fix/oauth-login-preserves-api-key branch from e0debe2 to aa4b99b Compare July 27, 2026 17:51
@Wibias

Wibias commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Maintainer takeover update for PR #491:

  • Rebased wonsh42:fix/oauth-login-preserves-api-key onto current dev (f3481669). The stray release: v2.7.40 commit was already present on dev and dropped as empty during rebase; package.json stays at the dev version (2.7.41) — no release bump in this bugfix.
  • Addressed review follow-ups in upsertOAuthProvider:
    • Omitted authMode with preservable key material now sets authMode: "key" (router only honors key override when mode is explicit). Explicit authMode: "oauth" still keeps subscription billing while carrying the key over.
    • Unsafe/blank active key with a usable pool promotes the first safe pool entry into apiKey and keeps key mode instead of falling back to oauth.
    • Shared sanitizeApiKeyValue with src/providers/api-keys.ts for the trim / no-CRLF checks.
  • Tests updated/added for omitted-mode and pool promotion.
  • Local verification on aa4b99b7: focused tests/oauth-upsert-preserves-api-key.test.ts PASS (11); bun run typecheck PASS; bun run privacy:scan PASS.

Waiting on CI on the rebased tip before merge. This path touches OAuth config writes — still needs maintainer security glance before merge.

@Wibias
Wibias marked this pull request as ready for review July 27, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants