diff --git a/.changeset/tangy-jeans-crash.md b/.changeset/tangy-jeans-crash.md new file mode 100644 index 00000000000..67459dfe646 --- /dev/null +++ b/.changeset/tangy-jeans-crash.md @@ -0,0 +1,6 @@ +--- +'@clerk/clerk-js': patch +'@clerk/shared': patch +--- + +Guard `ConfigureSSO` based on active organization diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index c96ae678925..a762311e98e 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -960,7 +960,7 @@ export class Clerk implements ClerkInterface { if (noOrganizationExists(this)) { if (this.#instanceType === 'development') { - throw new ClerkRuntimeError(warnings.cannotRenderComponentWhenOrgDoesNotExist, { + throw new ClerkRuntimeError(warnings.createCannotRenderComponentWhenOrgDoesNotExist('OrganizationProfile'), { code: CANNOT_RENDER_ORGANIZATION_MISSING_ERROR_CODE, }); } @@ -1131,7 +1131,7 @@ export class Clerk implements ClerkInterface { const userExists = !noUserExists(this); if (noOrganizationExists(this) && userExists) { if (this.#instanceType === 'development') { - throw new ClerkRuntimeError(warnings.cannotRenderComponentWhenOrgDoesNotExist, { + throw new ClerkRuntimeError(warnings.createCannotRenderComponentWhenOrgDoesNotExist('OrganizationProfile'), { code: CANNOT_RENDER_ORGANIZATION_MISSING_ERROR_CODE, }); } @@ -1462,28 +1462,43 @@ export class Clerk implements ClerkInterface { * @param props Configuration parameters. */ public mountConfigureSSO = (node: HTMLDivElement, props?: ConfigureSSOProps) => { - if (disabledSelfServeSSOFeature(this, this.environment)) { + const { isEnabled: isOrganizationsEnabled } = this.__internal_attemptToEnableEnvironmentSetting({ + for: 'organizations', + caller: 'ConfigureSSO', + onClose: () => { + throw new ClerkRuntimeError(warnings.cannotRenderAnyOrganizationComponent('ConfigureSSO'), { + code: CANNOT_RENDER_ORGANIZATIONS_DISABLED_ERROR_CODE, + }); + }, + }); + + if (!isOrganizationsEnabled) { + return; + } + + const userExists = !noUserExists(this); + if (noOrganizationExists(this) && userExists) { if (this.#instanceType === 'development') { - throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenDisabled, { - code: CANNOT_RENDER_SELF_SERVE_SSO_DISABLED_ERROR_CODE, + throw new ClerkRuntimeError(warnings.createCannotRenderComponentWhenOrgDoesNotExist('ConfigureSSO'), { + code: CANNOT_RENDER_ORGANIZATION_MISSING_ERROR_CODE, }); } return; } - if (disabledEmailAddressAttribute(this, this.environment)) { + if (disabledSelfServeSSOFeature(this, this.environment)) { if (this.#instanceType === 'development') { - throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenEmailAddressDisabled, { - code: CANNOT_RENDER_CONFIGURE_SSO_EMAIL_ADDRESS_DISABLED_ERROR_CODE, + throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenDisabled, { + code: CANNOT_RENDER_SELF_SERVE_SSO_DISABLED_ERROR_CODE, }); } return; } - if (noUserExists(this)) { + if (disabledEmailAddressAttribute(this, this.environment)) { if (this.#instanceType === 'development') { - throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenUserDoesNotExist, { - code: CANNOT_RENDER_USER_MISSING_ERROR_CODE, + throw new ClerkRuntimeError(warnings.cannotRenderConfigureSSOComponentWhenEmailAddressDisabled, { + code: CANNOT_RENDER_CONFIGURE_SSO_EMAIL_ADDRESS_DISABLED_ERROR_CODE, }); } return; diff --git a/packages/shared/src/internal/clerk-js/componentGuards.ts b/packages/shared/src/internal/clerk-js/componentGuards.ts index 06f9ac443b9..0ab6a5a7595 100644 --- a/packages/shared/src/internal/clerk-js/componentGuards.ts +++ b/packages/shared/src/internal/clerk-js/componentGuards.ts @@ -46,8 +46,8 @@ export const disabledAllAPIKeysFeatures: ComponentGuard = (_, environment) => { return disabledUserAPIKeysFeature(_, environment) && disabledOrganizationAPIKeysFeature(_, environment); }; -export const disabledSelfServeSSOFeature: ComponentGuard = (_, environment) => { - return !environment?.userSettings.enterpriseSSO.self_serve_sso; +export const disabledSelfServeSSOFeature: ComponentGuard = (clerk, environment) => { + return !environment?.userSettings.enterpriseSSO.self_serve_sso || !clerk.organization?.selfServeSSOEnabled; }; export const disabledEmailAddressAttribute: ComponentGuard = (_, environment) => { diff --git a/packages/shared/src/internal/clerk-js/warnings.ts b/packages/shared/src/internal/clerk-js/warnings.ts index bb9497e7ea2..e6af32fd689 100644 --- a/packages/shared/src/internal/clerk-js/warnings.ts +++ b/packages/shared/src/internal/clerk-js/warnings.ts @@ -10,12 +10,20 @@ const createMessageForDisabledOrganizations = ( | 'OrganizationSwitcher' | 'OrganizationList' | 'CreateOrganization' - | 'TaskChooseOrganization', + | 'TaskChooseOrganization' + | 'ConfigureSSO', ) => { return formatWarning( `The <${componentName}/> cannot be rendered when the feature is turned off. Visit 'dashboard.clerk.com' to enable the feature. Since the feature is turned off, this is no-op.`, ); }; + +const createCannotRenderComponentWhenOrgDoesNotExist = (componentName: 'OrganizationProfile' | 'ConfigureSSO') => { + return formatWarning( + `<${componentName}/> cannot render unless an organization is active. Since no organization is currently active, this is no-op.`, + ); +}; + const createMessageForDisabledBilling = (componentName: 'PricingTable' | 'Checkout' | 'PlanDetails') => { return formatWarning( `The <${componentName}/> component cannot be rendered when billing is disabled. Visit 'https://dashboard.clerk.com/last-active?path=billing/settings' to follow the necessary steps to enable billing. Since billing is disabled, this is no-op.`, @@ -45,7 +53,7 @@ const warnings = { 'The component cannot render when a user has a pending task, unless the application allows multiple sessions. Since a user is signed in and this application only allows a single session, Clerk is redirecting to the task instead.', cannotRenderComponentWhenUserDoesNotExist: ' cannot render unless a user is signed in. Since no user is signed in, this is no-op.', - cannotRenderComponentWhenOrgDoesNotExist: ` cannot render unless an organization is active. Since no organization is currently active, this is no-op.`, + createCannotRenderComponentWhenOrgDoesNotExist, cannotRenderAnyOrganizationComponent: createMessageForDisabledOrganizations, cannotRenderAnyBillingComponent: createMessageForDisabledBilling, cannotOpenUserProfile: diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index e840032f4f6..c7e87bcd2d2 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -1644,6 +1644,7 @@ export type __internal_AttemptToEnableEnvironmentSettingParams = { | 'OrganizationList' | 'CreateOrganization' | 'TaskChooseOrganization' + | 'ConfigureSSO' | 'useOrganizationList' | 'useOrganization'; onClose?: () => void;