Skip to content

Commit 0552fbf

Browse files
committed
fix(storage): prevent order-dependent org fallback account binding
1 parent 954ba9b commit 0552fbf

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

lib/storage.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,12 @@ function deduplicateAccountsByRefreshToken<T extends AccountLike>(accounts: T[])
461461
remainingFallbacks.push(fallbackIndex);
462462
continue;
463463
}
464+
const preferredAccountId = getAccountIdKey(currentPreferred);
465+
const sourceAccountId = getAccountIdKey(source);
466+
if (!preferredAccountId && sourceAccountId) {
467+
remainingFallbacks.push(fallbackIndex);
468+
continue;
469+
}
464470

465471
if (!canMergeByRefreshToken(currentPreferred, source)) {
466472
remainingFallbacks.push(fallbackIndex);

test/storage.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,39 @@ describe("storage", () => {
10771077
expect(result?.accounts.map((account) => account.organizationId).sort()).toEqual(["org-1", "org-2"]);
10781078
});
10791079

1080+
it("does not bind org-scoped entry with empty accountId to fallback accountId based on order", () => {
1081+
const firstOrder = normalizeAccountStorage({
1082+
version: 3,
1083+
activeIndex: 0,
1084+
accounts: [
1085+
{ organizationId: "org-1", refreshToken: "shared-refresh", addedAt: 1, lastUsed: 1 },
1086+
{ accountId: "workspace-a", refreshToken: "shared-refresh", addedAt: 2, lastUsed: 2 },
1087+
{ accountId: "workspace-b", refreshToken: "shared-refresh", addedAt: 3, lastUsed: 3 },
1088+
],
1089+
});
1090+
const secondOrder = normalizeAccountStorage({
1091+
version: 3,
1092+
activeIndex: 0,
1093+
accounts: [
1094+
{ organizationId: "org-1", refreshToken: "shared-refresh", addedAt: 1, lastUsed: 1 },
1095+
{ accountId: "workspace-b", refreshToken: "shared-refresh", addedAt: 2, lastUsed: 2 },
1096+
{ accountId: "workspace-a", refreshToken: "shared-refresh", addedAt: 3, lastUsed: 3 },
1097+
],
1098+
});
1099+
1100+
for (const normalized of [firstOrder, secondOrder]) {
1101+
expect(normalized?.accounts).toHaveLength(3);
1102+
const orgScoped = normalized?.accounts.find((account) => account.organizationId === "org-1");
1103+
expect(orgScoped).toBeDefined();
1104+
expect(orgScoped?.accountId).toBeUndefined();
1105+
const noOrgAccountIds = normalized?.accounts
1106+
.filter((account) => !account.organizationId)
1107+
.map((account) => account.accountId)
1108+
.sort();
1109+
expect(noOrgAccountIds).toEqual(["workspace-a", "workspace-b"]);
1110+
}
1111+
});
1112+
10801113
it("retains legacy no-organization dedupe semantics", () => {
10811114
const data = {
10821115
version: 3,

0 commit comments

Comments
 (0)