Skip to content

fix(oauth): keep the Kiro profileArn on IAM Identity Center logins - #10725

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.50from
MichaelYcJo:fix/kiro-idc-profilearn
Aug 20, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.50from
MichaelYcJo:fix/kiro-idc-profilearn

Conversation

@MichaelYcJo

Copy link
Copy Markdown
Contributor

A Kiro connection added through "Your organization (AWS IAM Identity Center)" now keeps its Q Developer profileArn. Before this it was persisted as a Builder ID connection with no ARN, and every usage lookup for it returned 403.

The symptom

On an instance with 8 Kiro connections, only the ones added through the IdC flow failed:

  • The connection tests fine and shows Connected; chat requests work normally.
  • The quota card shows the plan as Unknown with no credit bar.
  • GET /api/usage/<id> returns {"message":"Kiro quota API rejected the current token. Chat may still work.","quotas":{}}.

Connections added through AWS Builder ID on the same instance returned plan: "KIRO POWER" with credits, so the failure looked account-specific rather than flow-specific. It is not: subscription tier, plan source, IdC application assignment and user attributes were all identical to the working accounts.

Why it happens

Checked directly against CodeWhisperer with the account's own SSO token:

Call Result
ListAvailableProfiles 200 — returns the organization's profile ARN
GetUsageLimits without profileArn 403 AccessDeniedException: User is not authorized to make this call.
GetUsageLimits with profileArn 200 — subscriptionTitle: "KIRO POWER"

An IdC token has to be bound to the Q Developer profile; a Builder ID token does not need one. That is why only IdC connections break, and why the failure surfaces at the quota call rather than at login — the profile lookup itself succeeds without an ARN, so registration looks healthy.

The ARN was never stored because _authMethod was dropped between the device-code request and the poll:

  1. requestDeviceCode marks the login _authMethod: "idc" when a startUrl is present.
  2. OAuthModal forwarded only _clientId / _clientSecret / _region into the poll request.
  3. pollToken fell back to "builder-id".
  4. postExchange returns early for "builder-id", so ListAvailableProfiles never ran.
  5. mapTokens stored the connection with the wrong authMethod and no profileArn.

The fix

Forward _authMethod alongside the other device-code fields. Builder ID logins are unaffected — they have no profile and the lookup is still skipped, so no extra region probes are added for them.

Before After
Connection added via IdC stored as authMethod: "builder-id", no profileArn stored as authMethod: "idc" with the discovered profileArn
Its quota card plan Unknown, no credits plan and credits shown
Connection added via Builder ID unchanged unchanged

Verification

TDD — tests/unit/kiro-idc-profilearn-extradata.test.ts fails on the base commit with

OAuthModal must forward _authMethod so pollToken does not fall back to builder-id

and passes with the fix (5/5). It pins the whole chain, so a future edit that drops any link in it fails the suite rather than silently downgrading IdC logins again.

Real environment — reproduced on a running instance, then confirmed the mechanism by writing the ARN into the affected connection by hand:

PUT /api/providers/<id>  {"providerSpecificData":{"profileArn":"<org profile arn>"}}
GET /api/usage/<id>      -> {"plan":"KIRO POWER","quotas":{"credit":{...}}}

Checks run

Command Result
node --import tsx/esm --test tests/unit/kiro-idc-profilearn-extradata.test.ts 5 passed
oauth-modal-typescript-regressions + oauth-modal-grok-cli-paste-7610 + kiro-iam-profilearn-usage 13 passed
npx eslint on the changed files clean
npm run typecheck:core 9 pre-existing errors, all in open-sse/services/compression/** (omniglyph exports), none in the changed files

Note for reviewers

⚠️ base-red inherited: #9985 — release/v3.8.50 was already red when this branch was cut.

A Kiro connection added through "Your organization (AWS IAM Identity Center)" was
persisted as a Builder ID one, so providerSpecificData carried no profileArn. Every
CodeWhisperer usage call was then made unbound to the Q Developer profile and AWS
answered 403 "User is not authorized to make this call" — the quota card showed
"Kiro quota API rejected the current token. Chat may still work." while chat itself
kept working, and the plan badge stayed Unknown.

requestDeviceCode already marks IdC logins with _authMethod: "idc" when a startUrl is
present, but OAuthModal copied only _clientId/_clientSecret/_region into the poll
request. pollToken therefore fell back to "builder-id", postExchange returned early
without running the ListAvailableProfiles lookup, and mapTokens stored the connection
with neither the right authMethod nor a profileArn.

Builder ID logins are unaffected: they have no profile and the lookup is still skipped.
@diegosouzapw
diegosouzapw merged commit 83c77fb into diegosouzapw:release/v3.8.50 Aug 20, 2026
5 checks passed
alvinveroy added a commit to alvinveroy/OmniRoute that referenced this pull request Sep 3, 2026
Resolves the PR's dirty merge state: keeps upstream's Kiro IDC profileArn
PROJECT_ROUTE_ERROR block (diegosouzapw#10725) ahead of the Sentinel/Turnstile check and
retains this branch's diegosouzapw#8813 comment refinement on the Sentinel block.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…iegosouzapw#10725)

Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
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.

2 participants