Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/friendly-adults-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@clerk/shared": patch
"@clerk/testing": patch
---

Fixed an issue where API keys in `<UserProfile />` are showing organization API keys.
35 changes: 35 additions & 0 deletions integration/tests/machine-auth/component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,41 @@ testAgainstRunningApps({
await u.page.unrouteAll();
});

test('UserProfile API keys uses user ID as subject even when organization is active', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });

const admin = await u.services.users.getUser({ email: fakeAdmin.email });
expect(admin).toBeDefined();
const userId = admin.id;

await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeAdmin.email, password: fakeAdmin.password });
await u.po.expect.toBeSignedIn();

await u.po.organizationSwitcher.goTo();
await u.po.organizationSwitcher.waitForMounted();
await u.po.organizationSwitcher.waitForAnOrganizationToSelected();

// Capture the subject parameter
let capturedSubject: string | null = null;
await u.page.route('**/api_keys*', async route => {
const url = new URL(route.request().url());
capturedSubject = url.searchParams.get('subject');
await route.continue();
});

await u.po.page.goToRelative('/user');
await u.po.userProfile.waitForMounted();
await u.po.userProfile.switchToAPIKeysTab();

// Verify the subject parameter is the user ID, not the organization ID
expect(capturedSubject).toBe(userId);
expect(capturedSubject).not.toBe(fakeOrganization.organization.id);

await u.page.unrouteAll();
});

test('standalone API keys component in user context based on user_api_keys_enabled', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });

Expand Down
4 changes: 1 addition & 3 deletions packages/shared/src/react/hooks/useAPIKeys.rq.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ export function useAPIKeys<T extends UseAPIKeysParams>(params?: T): UseAPIKeysRe
keys: createCacheKeys({
stablePrefix: STABLE_KEYS.API_KEYS_KEY,
authenticated: Boolean(clerk.user),
tracked: {
subject: safeValues.subject,
},
tracked: {},
untracked: {
args: hookParams,
},
Expand Down
4 changes: 1 addition & 3 deletions packages/shared/src/react/hooks/useAPIKeys.swr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,7 @@ export function useAPIKeys<T extends UseAPIKeysParams>(params?: T): UseAPIKeysRe
keys: createCacheKeys({
stablePrefix: STABLE_KEYS.API_KEYS_KEY,
authenticated: Boolean(clerk.user),
tracked: {
subject: safeValues.subject,
},
tracked: {},
untracked: {
args: hookParams,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export const createUserProfileComponentPageObject = (testArgs: { page: EnhancedP
switchToBillingTab: async () => {
await page.getByText(/Billing/i).click();
},
switchToAPIKeysTab: async () => {
await page.getByText(/API keys/i).click();
},
waitForMounted: () => {
return page.waitForSelector('.cl-userProfile-root', { state: 'attached' });
},
Expand Down
Loading