diff --git a/.changeset/oauth-consent-last-active-org.md b/.changeset/oauth-consent-last-active-org.md
new file mode 100644
index 00000000000..1af3cc141b9
--- /dev/null
+++ b/.changeset/oauth-consent-last-active-org.md
@@ -0,0 +1,5 @@
+---
+"@clerk/ui": patch
+---
+
+Default the organization selection in `` to the user's last active organization, falling back to the first membership when it is not set or no longer available.
diff --git a/packages/ui/src/components/OAuthConsent/OAuthConsent.tsx b/packages/ui/src/components/OAuthConsent/OAuthConsent.tsx
index 394fd953833..21d5fac767a 100644
--- a/packages/ui/src/components/OAuthConsent/OAuthConsent.tsx
+++ b/packages/ui/src/components/OAuthConsent/OAuthConsent.tsx
@@ -46,8 +46,11 @@ function _OAuthConsent() {
}))
: [];
+ const lastActiveOrgId = clerk.session?.lastActiveOrganizationId;
+ const defaultOrg = orgOptions.find(o => o.value === lastActiveOrgId)?.value ?? orgOptions[0]?.value ?? null;
+
const [selectedOrg, setSelectedOrg] = useState(null);
- const effectiveOrg = selectedOrg ?? orgOptions[0]?.value ?? null;
+ const effectiveOrg = selectedOrg ?? defaultOrg;
// onAllow and onDeny are always provided as a pair by the accounts portal.
const hasContextCallbacks = Boolean(ctx.onAllow || ctx.onDeny);
diff --git a/packages/ui/src/components/OAuthConsent/__tests__/OAuthConsent.test.tsx b/packages/ui/src/components/OAuthConsent/__tests__/OAuthConsent.test.tsx
index c641e0c69ba..dce4347d6fd 100644
--- a/packages/ui/src/components/OAuthConsent/__tests__/OAuthConsent.test.tsx
+++ b/packages/ui/src/components/OAuthConsent/__tests__/OAuthConsent.test.tsx
@@ -415,5 +415,87 @@ describe('OAuthConsent', () => {
expect(form.querySelector('input[name="organization_id"]')).toBeNull();
});
});
+
+ it('defaults the selected org to session.lastActiveOrganizationId when it matches a membership', async () => {
+ const { wrapper, fixtures, props } = await createFixtures(f => {
+ f.withUser({
+ email_addresses: ['jane@example.com'],
+ organization_memberships: [
+ { id: 'org_1', name: 'Acme Corp' },
+ { id: 'org_2', name: 'Globex' },
+ { id: 'org_3', name: 'Initech' },
+ ],
+ });
+ f.withOrganizations();
+ });
+
+ fixtures.clerk.session.lastActiveOrganizationId = 'org_3';
+
+ props.setProps({ componentName: 'OAuthConsent', __internal_enableOrgSelection: true } as any);
+ mockOAuthApplication(fixtures.clerk, { getConsentInfo: vi.fn().mockResolvedValue(fakeConsentInfo) });
+
+ const { baseElement } = render(, { wrapper });
+
+ await waitFor(() => {
+ const form = baseElement.querySelector('form[action*="/v1/me/oauth/consent/"]')!;
+ const hiddenInput = form.querySelector('input[name="organization_id"]') as HTMLInputElement | null;
+ expect(hiddenInput).not.toBeNull();
+ expect(hiddenInput!.value).toBe('org_3');
+ });
+ });
+
+ it('falls back to the first membership when lastActiveOrganizationId does not match any membership', async () => {
+ const { wrapper, fixtures, props } = await createFixtures(f => {
+ f.withUser({
+ email_addresses: ['jane@example.com'],
+ organization_memberships: [
+ { id: 'org_1', name: 'Acme Corp' },
+ { id: 'org_2', name: 'Globex' },
+ ],
+ });
+ f.withOrganizations();
+ });
+
+ fixtures.clerk.session.lastActiveOrganizationId = 'org_deleted';
+
+ props.setProps({ componentName: 'OAuthConsent', __internal_enableOrgSelection: true } as any);
+ mockOAuthApplication(fixtures.clerk, { getConsentInfo: vi.fn().mockResolvedValue(fakeConsentInfo) });
+
+ const { baseElement } = render(, { wrapper });
+
+ await waitFor(() => {
+ const form = baseElement.querySelector('form[action*="/v1/me/oauth/consent/"]')!;
+ const hiddenInput = form.querySelector('input[name="organization_id"]') as HTMLInputElement | null;
+ expect(hiddenInput).not.toBeNull();
+ expect(hiddenInput!.value).toBe('org_1');
+ });
+ });
+
+ it('falls back to the first membership when lastActiveOrganizationId is null', async () => {
+ const { wrapper, fixtures, props } = await createFixtures(f => {
+ f.withUser({
+ email_addresses: ['jane@example.com'],
+ organization_memberships: [
+ { id: 'org_1', name: 'Acme Corp' },
+ { id: 'org_2', name: 'Globex' },
+ ],
+ });
+ f.withOrganizations();
+ });
+
+ fixtures.clerk.session.lastActiveOrganizationId = null;
+
+ props.setProps({ componentName: 'OAuthConsent', __internal_enableOrgSelection: true } as any);
+ mockOAuthApplication(fixtures.clerk, { getConsentInfo: vi.fn().mockResolvedValue(fakeConsentInfo) });
+
+ const { baseElement } = render(, { wrapper });
+
+ await waitFor(() => {
+ const form = baseElement.querySelector('form[action*="/v1/me/oauth/consent/"]')!;
+ const hiddenInput = form.querySelector('input[name="organization_id"]') as HTMLInputElement | null;
+ expect(hiddenInput).not.toBeNull();
+ expect(hiddenInput!.value).toBe('org_1');
+ });
+ });
});
});