Skip to content

fix(kiro): treat desktop refresh "Bad credentials" as a terminal grant refusal - #7054

Draft
Veritas-7 wants to merge 1 commit into
lidge-jun:devfrom
Veritas-7:fix/kiro-refresh-bad-credentials
Draft

Veritas-7 wants to merge 1 commit into
lidge-jun:devfrom
Veritas-7:fix/kiro-refresh-bad-credentials

Conversation

@Veritas-7

@Veritas-7 Veritas-7 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

When a Kiro desktop-auth account (social login, no registered AWS SSO client) holds a dead refresh token, the account is never flagged for reauthentication. It stays healthy and logged in while every refresh fails.

The desktop refresh endpoint POST https://prod.us-east-1.auth.desktop.kiro.dev/refreshToken answers an invalid refresh token with HTTP 401 and a body whose only key is message: {"message":"Bad credentials"} (observed 2026-10-13). It has no OAuth error field. kiroTokenRefreshError in src/oauth/kiro.ts only reads payload.error against KIRO_TERMINAL_REFRESH_ERRORS, so oauthError stays undefined. terminal() in src/oauth/index.ts treats a KiroTokenRefreshError as terminal only when a 400/401 carries an oauthError, so the account is never marked needsReauth.

The fix is narrow. For the desktop endpoint only (not the AWS SSO OIDC refresh), HTTP 401 together with message === "Bad credentials" (exact match) is classified as a terminal grant refusal. It is surfaced under the fixed code bad_credentials, and the raw upstream text is never echoed. The existing generation-fenced quarantine path then marks the rejected generation needsReauth, exactly as it does for invalid_grant. Nothing else becomes terminal: any other 401 message, the same message with another status, the same pair from the AWS SSO endpoint, 5xx and network failures all stay retryable. The #6716 refresh-attention behavior for AWS SSO invalid_request is unchanged.

One interaction worth calling out: in refreshKiroToken, an AWS SSO 400 can fall back to a rotated local kiro-cli credential, and that recovery may use the desktop endpoint. If the recovery attempt itself gets the desktop 401 Bad credentials, the account is now quarantined instead of staying retryable. At that point both the stored token and the local CLI token have been refused, so reauthentication is the only way forward. A dedicated regression covers this path: the AWS SSO 400 is followed by the desktop 401 Bad credentials, and the test asserts the request order (OIDC, then desktop), OAuthLoginRequiredError and stored needsReauth: true.

Changed files:

  • src/oauth/kiro.ts: recognize the exact desktop 401 Bad credentials reply in kiroTokenRefreshError.
  • tests/oauth/oauth-kiro-refresh-attention.test.ts: one positive regression plus one CLI-recovery regression (desktop 401 Bad credentials → OAuthLoginRequiredError, stored needsReauth: true, loggedIn: false, a single request to the desktop endpoint) and three negative cases (desktop 401 with another message, desktop 400 Bad credentials, AWS SSO 401 Bad credentials → not quarantined).
  • structure/providers-and-adapters.md: one sentence on the Kiro refresh contract paragraph, kept within the file's line budget.

Verification

Base: dev at e2886a64a (rebased). Earlier figures were measured on 582589c23/60752ec3c. Tests were run with Bun 1.4.2 (the runtime the package ships); CONTRIBUTING pins 1.4.3 for the suite runner, so CI is the authoritative run.

  • bun test ./tests/oauth/oauth-kiro-refresh-attention.test.ts: 27 pass, 0 fail (22 existing + 5 new).
  • Mutation checks, each with only src/oauth/kiro.ts altered:
    • Fix reverted: 25 pass, 2 fail (the positive desktop Bad credentials case and the CLI-recovery case).
    • Message check dropped (any desktop 401 terminal): 1 fail (desktop 401 with another message).
    • Endpoint check dropped (AWS SSO included): 1 fail (AWS SSO 401 Bad credentials).
    • Status check dropped (any status with that message): 1 fail (desktop 400 Bad credentials).
  • After rebasing onto e2886a64a: bun test ./tests/oauth/oauth-kiro-refresh-attention.test.ts ./tests/providers/kiro/kiro-oauth.test.ts ./tests/server/server-kiro-oauth-401-replay.test.ts: 92 pass, 0 fail; bun test ./tests/oauth/oauth-refresh.test.ts: 67 pass, 0 fail; bun run typecheck and bun run structure:check pass.
  • bun run typecheck: passed.
  • bun run structure:check: passed. The doc file stays at its 600-line budget.
  • bun run privacy:scan: passed.
  • git diff --check: clean.

I did not run the full local suite (bun run test). The change is confined to one error classifier, and the focused files above cover Kiro refresh, refresh attention, the generic OAuth refresh lock and the 401 replay path. Required CI on the PR head still has to pass.

Checklist

  • Scope stays focused and avoids unrelated cleanup: one classifier branch, focused regression tests, and one contract sentence. No change to the AWS SSO attention path or to the terminal predicate in src/oauth/index.ts.
  • Docs or release notes were updated when needed: the structure/providers-and-adapters.md Kiro refresh paragraph now records the desktop Bad credentials verdict.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults: the upstream message is matched exactly and never surfaced, and terminality is not widened to other 4xx replies (the negative tests pin this). This touches an authentication surface, so it needs maintainer sponsorship (maintainer-sponsored) per CONTRIBUTING.

🤖 Generated with Claude Code

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • Required local validation passed; commands, results, and any full-suite exception are documented.

  • I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes
    • Kiro desktop refresh now treats an HTTP 401 response with the exact “Bad credentials” message as a terminal login error and quarantines the affected account.
    • Other error responses and AWS SSO refresh behavior remain unchanged.
  • Documentation
    • Clarified which Kiro refresh response triggers this handling.

@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Oct 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/kiro.ts.

@github-actions github-actions Bot added the bug Something isn't working label Oct 13, 2026
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • hygiene: unsponsored_surface.

What to do

  • Fix unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/kiro.ts.

Review readiness checklist

  • ✅ Required local validation passed; commands, results, and any full-suite exception are documented.
  • ✅ I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

✅ 4/4 boxes ticked.

This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 49141e06-8402-4ce3-a52a-f82264115f50
📥 Commits

Reviewing files that changed from the base of the PR and between a29cb3d and 7fab71e.

📒 Files selected for processing (3)
  • src/oauth/kiro.ts
  • structure/providers-and-adapters.md
  • tests/oauth/oauth-kiro-refresh-attention.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

Kiro refresh handling now maps an HTTP 401 response with the exact message "Bad credentials" from the desktop endpoint to a fixed OAuth error code. Tests cover quarantine for matching responses and no quarantine for other desktop or AWS SSO responses.

Changes: Kiro refresh rejection handling

Layer / File(s) Summary
Recognize and verify the desktop rejection
src/oauth/kiro.ts, structure/providers-and-adapters.md, tests/oauth/oauth-kiro-refresh-attention.test.ts
The refresh logic maps the exact desktop HTTP 401 response to bad_credentials. The documentation specifies the response condition. Tests cover quarantine during desktop refresh and CLI recovery, and verify that other desktop and AWS SSO failures do not quarantine the account.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 7fab7

The targeted rejection handling appears ready to merge after normal required checks pass.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
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.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: treating the exact Kiro desktop refresh response HTTP 401 with "Bad credentials" as a terminal grant refusal.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
github-actions Bot marked this pull request as draft October 13, 2026 15:11
…t refusal

The Kiro desktop refresh endpoint answers a dead refresh token with HTTP
401 and a bare {"message":"Bad credentials"} body, without an OAuth error
code, so the account was never marked needsReauth and stayed healthy while
every refresh failed. Classify exactly that desktop 401 reply under the
fixed code bad_credentials so the existing generation-fenced quarantine
path applies. AWS SSO refreshes, other 401 messages, other statuses, 5xx
and network failures stay retryable.

Assisted-by: Claude Opus 5.5 (Claude Code)
@lidge-jun

Copy link
Copy Markdown
Owner

Carried onto an upstream branch in #7062 (with a Co-authored-by trailer) so the repository CI can run. It is held there for the security review that MAINTAINERS.md requires for authentication changes. Leaving this PR open until that review concludes.

lidge-jun added a commit that referenced this pull request Oct 13, 2026
…top Bad credentials (#7053, #7054) (#7062)

* fix(kiro): accept authorized social device grants

Carries #7053. Preserve token, profile, principal, and HTTP validation.

Co-authored-by: Veritas-7 <234569343+Veritas-7@users.noreply.github.com>

* fix(kiro): quarantine exact desktop bad-credentials refusals

Carries #7054. Keep AWS SSO and other status/message pairs retryable.

Co-authored-by: Veritas-7 <234569343+Veritas-7@users.noreply.github.com>

* fix(chatgpt): preserve launcher when app inspection fails

Carries #7055. Report unknown inspection state and refuse an unconfirmed restart.

Co-authored-by: lcxhh <lcxhh521@gmail.com>

* fix(proxy): bound SOCKS5 TLS handshake lifetime

Carries #7056. Clear deadline and listeners on every TLS handshake exit while keeping certificate verification.

Co-authored-by: lcxhh <lcxhh521@gmail.com>

* docs: triage exceeded-retry-limit 429 errors

Carries #6925. Align refresh release conditions and the resolved credit rediscovery reference with current dev.

Co-authored-by: Howard-Jerry <197214646+Howard-Jerry@users.noreply.github.com>

---------

Co-authored-by: JUN <243035832+lidge-jun@users.noreply.github.com>
Co-authored-by: Veritas-7 <234569343+Veritas-7@users.noreply.github.com>
Co-authored-by: lcxhh <lcxhh521@gmail.com>
Co-authored-by: Howard-Jerry <197214646+Howard-Jerry@users.noreply.github.com>
Co-authored-by: jun <jun@juns-Mac-Studio.local>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants