diff --git a/.changeset/cool-dragons-march.md b/.changeset/cool-dragons-march.md new file mode 100644 index 00000000000..1927703947f --- /dev/null +++ b/.changeset/cool-dragons-march.md @@ -0,0 +1,8 @@ +--- +"@clerk/clerk-js": patch +"@clerk/localizations": patch +"@clerk/shared": patch +"@clerk/ui": patch +--- + +Add support for configuring custom OpenID Connect enterprise connections through the Organization Profile. diff --git a/packages/clerk-js/src/core/resources/EnterpriseConnection.ts b/packages/clerk-js/src/core/resources/EnterpriseConnection.ts index 109e7775ce1..f50213ded64 100644 --- a/packages/clerk-js/src/core/resources/EnterpriseConnection.ts +++ b/packages/clerk-js/src/core/resources/EnterpriseConnection.ts @@ -59,7 +59,11 @@ function oauthConfigFromJSON(data: EnterpriseOAuthConfigJSON): EnterpriseOAuthCo name: data.name, clientId: data.client_id, providerKey: data.provider_key, + redirectUri: data.redirect_uri, discoveryUrl: data.discovery_url, + authUrl: data.auth_url, + tokenUrl: data.token_url, + userInfoUrl: data.user_info_url, logoPublicUrl: data.logo_public_url, requiresPkce: data.requires_pkce, createdAt: unixEpochToDate(data.created_at), @@ -73,7 +77,11 @@ function oauthConfigToJSON(data: EnterpriseOAuthConfigResource): EnterpriseOAuth name: data.name, client_id: data.clientId, provider_key: data.providerKey, + redirect_uri: data.redirectUri, discovery_url: data.discoveryUrl, + auth_url: data.authUrl, + token_url: data.tokenUrl, + user_info_url: data.userInfoUrl, logo_public_url: data.logoPublicUrl, requires_pkce: data.requiresPkce, created_at: data.createdAt?.getTime() ?? 0, diff --git a/packages/localizations/src/ar-SA.ts b/packages/localizations/src/ar-SA.ts index 1ba1b904de0..40994083186 100644 --- a/packages/localizations/src/ar-SA.ts +++ b/packages/localizations/src/ar-SA.ts @@ -243,6 +243,79 @@ export const arSA: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const arSA: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'تواصل مع مسؤول مؤسستك لترقية أذوناتك.', @@ -679,6 +756,10 @@ export const arSA: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'مزود SAML مخصص', google: undefined, diff --git a/packages/localizations/src/be-BY.ts b/packages/localizations/src/be-BY.ts index 507be784eb5..83232a15181 100644 --- a/packages/localizations/src/be-BY.ts +++ b/packages/localizations/src/be-BY.ts @@ -243,6 +243,79 @@ export const beBY: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const beBY: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Звярніцеся да адміністратара вашай арганізацыі, каб павысіць вашы дазволы.', @@ -680,6 +757,10 @@ export const beBY: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Карыстальніцкі правайдэр SAML', google: undefined, diff --git a/packages/localizations/src/bg-BG.ts b/packages/localizations/src/bg-BG.ts index 72af2e579f8..d3ac2d80177 100644 --- a/packages/localizations/src/bg-BG.ts +++ b/packages/localizations/src/bg-BG.ts @@ -244,6 +244,79 @@ export const bgBG: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -628,6 +701,10 @@ export const bgBG: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Свържете се с администратора на вашата организация, за да повишите разрешенията си.', @@ -681,6 +758,10 @@ export const bgBG: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Персонализиран SAML доставчик', google: undefined, diff --git a/packages/localizations/src/bn-IN.ts b/packages/localizations/src/bn-IN.ts index 50d7f11f77c..e4b855441f3 100644 --- a/packages/localizations/src/bn-IN.ts +++ b/packages/localizations/src/bn-IN.ts @@ -249,6 +249,79 @@ export const bnIN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const bnIN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'আপনার অনুমতি আপগ্রেড করতে আপনার সংস্থার প্রশাসকের সাথে যোগাযোগ করুন।', @@ -686,6 +763,10 @@ export const bnIN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'কাস্টম SAML প্রদানকারী', google: undefined, diff --git a/packages/localizations/src/ca-ES.ts b/packages/localizations/src/ca-ES.ts index 74fe181dda4..5609cfa4b72 100644 --- a/packages/localizations/src/ca-ES.ts +++ b/packages/localizations/src/ca-ES.ts @@ -250,6 +250,79 @@ export const caES: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const caES: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: "Contacta amb l'administrador de la teva organització per ampliar els teus permisos.", @@ -687,6 +764,10 @@ export const caES: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Proveïdor SAML personalitzat', google: undefined, diff --git a/packages/localizations/src/cs-CZ.ts b/packages/localizations/src/cs-CZ.ts index 2b0ada91bd6..4518dcb268d 100644 --- a/packages/localizations/src/cs-CZ.ts +++ b/packages/localizations/src/cs-CZ.ts @@ -247,6 +247,79 @@ export const csCZ: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -631,6 +704,10 @@ export const csCZ: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontaktujte správce vaší organizace pro rozšíření vašich oprávnění.', @@ -684,6 +761,10 @@ export const csCZ: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Vlastní poskytovatel SAML', google: undefined, diff --git a/packages/localizations/src/da-DK.ts b/packages/localizations/src/da-DK.ts index cd1c1d6056b..a0c308472a5 100644 --- a/packages/localizations/src/da-DK.ts +++ b/packages/localizations/src/da-DK.ts @@ -243,6 +243,79 @@ export const daDK: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const daDK: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontakt din organisations administrator for at opgradere dine tilladelser.', @@ -679,6 +756,10 @@ export const daDK: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Brugerdefineret SAML-udbyder', google: undefined, diff --git a/packages/localizations/src/de-DE.ts b/packages/localizations/src/de-DE.ts index f0c1b41dd1c..748ec81cd65 100644 --- a/packages/localizations/src/de-DE.ts +++ b/packages/localizations/src/de-DE.ts @@ -249,6 +249,79 @@ export const deDE: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const deDE: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Wenden Sie sich an Ihren Organisationsadministrator, um Ihre Berechtigungen zu erweitern.', @@ -687,6 +764,10 @@ export const deDE: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Benutzerdefinierter SAML-Anbieter', google: undefined, diff --git a/packages/localizations/src/el-GR.ts b/packages/localizations/src/el-GR.ts index f97b52aae28..3605d6956b7 100644 --- a/packages/localizations/src/el-GR.ts +++ b/packages/localizations/src/el-GR.ts @@ -243,6 +243,79 @@ export const elGR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const elGR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Επικοινωνήστε με τον διαχειριστή του οργανισμού σας για να αναβαθμίσετε τις άδειές σας.', @@ -680,6 +757,10 @@ export const elGR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Προσαρμοσμένος πάροχος SAML', google: undefined, diff --git a/packages/localizations/src/en-GB.ts b/packages/localizations/src/en-GB.ts index c6c0a1c6818..65ae7776b4e 100644 --- a/packages/localizations/src/en-GB.ts +++ b/packages/localizations/src/en-GB.ts @@ -243,6 +243,79 @@ export const enGB: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const enGB: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: "Contact your organisation's administrator to upgrade your permissions.", @@ -679,6 +756,10 @@ export const enGB: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Custom SAML Provider', google: undefined, diff --git a/packages/localizations/src/en-US.ts b/packages/localizations/src/en-US.ts index 9f5c9abcc5f..7e8450b354b 100644 --- a/packages/localizations/src/en-US.ts +++ b/packages/localizations/src/en-US.ts @@ -240,6 +240,81 @@ export const enUS: LocalizationResource = { required: 'Required', }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: 'Client ID', + placeholder: 'Paste client ID here...', + }, + clientSecret: { + label: 'Client secret', + placeholder: 'Paste client secret here...', + }, + headerSubtitle: 'Add your application credentials', + paragraph: 'In your identity provider’s OIDC application, retrieve these values.', + }, + endpointsStep: { + discoveryUrl: { + description: + 'In your identity provider’s OIDC application, retrieve the discovery endpoint. Paste it below.', + label: 'Discovery endpoint', + placeholder: 'Paste URL here...', + }, + headerSubtitle: 'Add your identity provider’s endpoints', + manual: { + authUrl: { + label: 'Authorization URL', + placeholder: 'Paste URL here...', + }, + description: 'In your identity provider’s OIDC application, retrieve these values.', + tokenUrl: { + label: 'Token URL', + placeholder: 'Paste URL here...', + }, + userInfoUrl: { + label: 'User Info URL', + placeholder: 'Paste URL here...', + }, + }, + modes: { + ariaLabel: 'OIDC endpoint configuration method', + discoveryUrl: 'Add via discovery endpoint', + manual: 'Configure manually', + }, + }, + mainHeaderTitle: 'Configure your identity provider', + redirectUriStep: { + claims: { + description: 'Ensure your ID token includes the following claims:', + table: { + columns: { + attribute: 'Clerk attribute', + claim: 'ID token claim', + }, + rows: { + email: { + attribute: 'Primary email', + }, + firstName: { + attribute: 'First name', + }, + lastName: { + attribute: 'Last name', + }, + subject: { + attribute: 'External user ID', + }, + }, + }, + }, + headerSubtitle: 'Create a new OIDC application in your identity provider’s dashboard', + paragraph: + 'In your identity provider’s dashboard, create a new OIDC application that supports the authorization code grant type, and use the following redirect URI:', + redirectUri: { + label: 'Authorized redirect URI', + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: 'Assign users or groups to your SAML application', @@ -640,6 +715,11 @@ export const enUS: LocalizationResource = { }, mainHeaderTitle: 'Configure Okta Workforce', }, + unsupportedProvider: { + description: + 'This identity provider isn’t supported in this version of Clerk. Update to the latest version to finish setting it up.', + title: 'Unsupported provider', + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: "Contact your organization's administrator to upgrade your permissions.", @@ -695,6 +775,10 @@ export const enUS: LocalizationResource = { title: 'Reset connection', }, selectProviderStep: { + oidc: { + groupLabel: 'OpenID Connect (OIDC)', + oidcProvider: 'OIDC Provider', + }, saml: { customSaml: 'Custom SAML Provider', google: 'Google Workspace', diff --git a/packages/localizations/src/es-CR.ts b/packages/localizations/src/es-CR.ts index e91b5452bbf..763951e89ce 100644 --- a/packages/localizations/src/es-CR.ts +++ b/packages/localizations/src/es-CR.ts @@ -243,6 +243,79 @@ export const esCR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const esCR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contactá al administrador de tu organización para mejorar tus permisos.', @@ -680,6 +757,10 @@ export const esCR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Proveedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/es-ES.ts b/packages/localizations/src/es-ES.ts index 5a7885986b1..50145eb44c7 100644 --- a/packages/localizations/src/es-ES.ts +++ b/packages/localizations/src/es-ES.ts @@ -249,6 +249,79 @@ export const esES: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const esES: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contacte al administrador de su organización para ampliar sus permisos.', @@ -686,6 +763,10 @@ export const esES: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Proveedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/es-MX.ts b/packages/localizations/src/es-MX.ts index 9607e87a56a..1bc4a32c7fd 100644 --- a/packages/localizations/src/es-MX.ts +++ b/packages/localizations/src/es-MX.ts @@ -244,6 +244,79 @@ export const esMX: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -628,6 +701,10 @@ export const esMX: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contacta al administrador de tu organización para ampliar tus permisos.', @@ -681,6 +758,10 @@ export const esMX: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Proveedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/es-UY.ts b/packages/localizations/src/es-UY.ts index 51084f69606..e4a4f3cff3e 100644 --- a/packages/localizations/src/es-UY.ts +++ b/packages/localizations/src/es-UY.ts @@ -243,6 +243,79 @@ export const esUY: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const esUY: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contactá al administrador de tu organización para ampliar tus permisos.', @@ -680,6 +757,10 @@ export const esUY: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Proveedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/fa-IR.ts b/packages/localizations/src/fa-IR.ts index 0e472f1745f..418bf489df2 100644 --- a/packages/localizations/src/fa-IR.ts +++ b/packages/localizations/src/fa-IR.ts @@ -248,6 +248,79 @@ export const faIR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -632,6 +705,10 @@ export const faIR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'برای ارتقای مجوزهای خود با مدیر سازمان تماس بگیرید.', @@ -685,6 +762,10 @@ export const faIR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'ارائه‌دهنده SAML سفارشی', google: undefined, diff --git a/packages/localizations/src/fi-FI.ts b/packages/localizations/src/fi-FI.ts index 7d68f3789f3..6c5e925e4ee 100644 --- a/packages/localizations/src/fi-FI.ts +++ b/packages/localizations/src/fi-FI.ts @@ -249,6 +249,79 @@ export const fiFI: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const fiFI: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Ota yhteyttä organisaatiosi järjestelmänvalvojaan päivittääksesi oikeuksiasi.', @@ -686,6 +763,10 @@ export const fiFI: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Mukautettu SAML-palveluntarjoaja', google: undefined, diff --git a/packages/localizations/src/fr-FR.ts b/packages/localizations/src/fr-FR.ts index d1aeb515082..84777acd790 100644 --- a/packages/localizations/src/fr-FR.ts +++ b/packages/localizations/src/fr-FR.ts @@ -251,6 +251,79 @@ export const frFR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -635,6 +708,10 @@ export const frFR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: "Contactez l'administrateur de votre organisation pour étendre vos permissions.", @@ -688,6 +765,10 @@ export const frFR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Fournisseur SAML personnalisé', google: undefined, diff --git a/packages/localizations/src/he-IL.ts b/packages/localizations/src/he-IL.ts index 030d4df1157..c53bed8d69e 100644 --- a/packages/localizations/src/he-IL.ts +++ b/packages/localizations/src/he-IL.ts @@ -243,6 +243,79 @@ export const heIL: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const heIL: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'פנה למנהל הארגון שלך כדי לשדרג את ההרשאות שלך.', @@ -679,6 +756,10 @@ export const heIL: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'ספק SAML מותאם אישית', google: undefined, diff --git a/packages/localizations/src/hi-IN.ts b/packages/localizations/src/hi-IN.ts index cb9ddad1db6..0d429f2d76d 100644 --- a/packages/localizations/src/hi-IN.ts +++ b/packages/localizations/src/hi-IN.ts @@ -249,6 +249,79 @@ export const hiIN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const hiIN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'अपनी अनुमतियाँ अपग्रेड करने के लिए अपने संगठन के व्यवस्थापक से संपर्क करें।', @@ -686,6 +763,10 @@ export const hiIN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'कस्टम SAML प्रदाता', google: undefined, diff --git a/packages/localizations/src/hr-HR.ts b/packages/localizations/src/hr-HR.ts index 46061f89292..57d138a1021 100644 --- a/packages/localizations/src/hr-HR.ts +++ b/packages/localizations/src/hr-HR.ts @@ -250,6 +250,79 @@ export const hrHR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const hrHR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Obratite se administratoru vaše organizacije kako biste nadogradili svoja dopuštenja.', @@ -687,6 +764,10 @@ export const hrHR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Prilagođeni SAML pružatelj', google: undefined, diff --git a/packages/localizations/src/hu-HU.ts b/packages/localizations/src/hu-HU.ts index 075c0cc71f9..4fbdcd278bf 100644 --- a/packages/localizations/src/hu-HU.ts +++ b/packages/localizations/src/hu-HU.ts @@ -250,6 +250,79 @@ export const huHU: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const huHU: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Vegye fel a kapcsolatot szervezete adminisztrátorával a jogosultságai bővítéséhez.', @@ -688,6 +765,10 @@ export const huHU: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Egyéni SAML szolgáltató', google: undefined, diff --git a/packages/localizations/src/id-ID.ts b/packages/localizations/src/id-ID.ts index 740bdc0dbd1..e865afeb3b5 100644 --- a/packages/localizations/src/id-ID.ts +++ b/packages/localizations/src/id-ID.ts @@ -243,6 +243,79 @@ export const idID: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const idID: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Hubungi administrator organisasi Anda untuk meningkatkan izin Anda.', @@ -680,6 +757,10 @@ export const idID: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Penyedia SAML Khusus', google: undefined, diff --git a/packages/localizations/src/is-IS.ts b/packages/localizations/src/is-IS.ts index 3f9fd7f8f20..f6a9725bbb5 100644 --- a/packages/localizations/src/is-IS.ts +++ b/packages/localizations/src/is-IS.ts @@ -249,6 +249,79 @@ export const isIS: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const isIS: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Hafðu samband við stjórnanda fyrirtækisins þíns til að uppfæra heimildir þínar.', @@ -686,6 +763,10 @@ export const isIS: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Sérsniðinn SAML þjónustuaðili', google: undefined, diff --git a/packages/localizations/src/it-IT.ts b/packages/localizations/src/it-IT.ts index 725555948eb..33bb54cb212 100644 --- a/packages/localizations/src/it-IT.ts +++ b/packages/localizations/src/it-IT.ts @@ -249,6 +249,79 @@ export const itIT: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const itIT: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: "Contatta l'amministratore della tua organizzazione per ampliare i tuoi permessi.", @@ -686,6 +763,10 @@ export const itIT: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Provider SAML personalizzato', google: undefined, diff --git a/packages/localizations/src/ja-JP.ts b/packages/localizations/src/ja-JP.ts index 7650af51fd1..79040d358be 100644 --- a/packages/localizations/src/ja-JP.ts +++ b/packages/localizations/src/ja-JP.ts @@ -250,6 +250,79 @@ export const jaJP: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const jaJP: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: '権限をアップグレードするには、組織の管理者にお問い合わせください。', @@ -687,6 +764,10 @@ export const jaJP: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'カスタムSAMLプロバイダー', google: undefined, diff --git a/packages/localizations/src/kk-KZ.ts b/packages/localizations/src/kk-KZ.ts index 61c51ac5a68..0d1ac09634a 100644 --- a/packages/localizations/src/kk-KZ.ts +++ b/packages/localizations/src/kk-KZ.ts @@ -243,6 +243,79 @@ export const kkKZ: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const kkKZ: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Рұқсаттарыңызды жаңарту үшін ұйым әкімшісіне хабарласыңыз.', @@ -680,6 +757,10 @@ export const kkKZ: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Реттелетін SAML провайдері', google: undefined, diff --git a/packages/localizations/src/ko-KR.ts b/packages/localizations/src/ko-KR.ts index e58be892784..c1abc4a3deb 100644 --- a/packages/localizations/src/ko-KR.ts +++ b/packages/localizations/src/ko-KR.ts @@ -247,6 +247,79 @@ export const koKR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -631,6 +704,10 @@ export const koKR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: '권한을 업그레이드하려면 조직 관리자에게 문의하세요.', @@ -683,6 +760,10 @@ export const koKR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: '사용자 지정 SAML 공급자', google: undefined, diff --git a/packages/localizations/src/mn-MN.ts b/packages/localizations/src/mn-MN.ts index f7cb628da22..16af9e40f59 100644 --- a/packages/localizations/src/mn-MN.ts +++ b/packages/localizations/src/mn-MN.ts @@ -243,6 +243,79 @@ export const mnMN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const mnMN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Эрхээ дээшлүүлэхийн тулд байгууллагынхаа админтай холбогдоно уу.', @@ -680,6 +757,10 @@ export const mnMN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Хэрэглэгчийн тохируулсан SAML үйлчилгээ үзүүлэгч', google: undefined, diff --git a/packages/localizations/src/ms-MY.ts b/packages/localizations/src/ms-MY.ts index 666b3e8ef9b..a5080bba09c 100644 --- a/packages/localizations/src/ms-MY.ts +++ b/packages/localizations/src/ms-MY.ts @@ -251,6 +251,79 @@ export const msMY: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -635,6 +708,10 @@ export const msMY: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Hubungi pentadbir organisasi anda untuk menaik taraf kebenaran anda.', @@ -688,6 +765,10 @@ export const msMY: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Pembekal SAML Tersuai', google: undefined, diff --git a/packages/localizations/src/nb-NO.ts b/packages/localizations/src/nb-NO.ts index b8aa65cde7f..f6ca9bd2a0d 100644 --- a/packages/localizations/src/nb-NO.ts +++ b/packages/localizations/src/nb-NO.ts @@ -250,6 +250,79 @@ export const nbNO: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const nbNO: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontakt organisasjonens administrator for å oppgradere tillatelsene dine.', @@ -687,6 +764,10 @@ export const nbNO: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Egendefinert SAML-leverandør', google: undefined, diff --git a/packages/localizations/src/nl-BE.ts b/packages/localizations/src/nl-BE.ts index b68a542214a..679be3735fe 100644 --- a/packages/localizations/src/nl-BE.ts +++ b/packages/localizations/src/nl-BE.ts @@ -243,6 +243,79 @@ export const nlBE: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const nlBE: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Neem contact op met de beheerder van uw organisatie om uw rechten uit te breiden.', @@ -680,6 +757,10 @@ export const nlBE: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Aangepaste SAML-provider', google: undefined, diff --git a/packages/localizations/src/nl-NL.ts b/packages/localizations/src/nl-NL.ts index 4d4ee65b96d..7475561c530 100644 --- a/packages/localizations/src/nl-NL.ts +++ b/packages/localizations/src/nl-NL.ts @@ -243,6 +243,79 @@ export const nlNL: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const nlNL: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Neem contact op met de beheerder van je organisatie om je rechten uit te breiden.', @@ -680,6 +757,10 @@ export const nlNL: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Aangepaste SAML-provider', google: undefined, diff --git a/packages/localizations/src/pl-PL.ts b/packages/localizations/src/pl-PL.ts index 882d79fb7bc..c752dae2933 100644 --- a/packages/localizations/src/pl-PL.ts +++ b/packages/localizations/src/pl-PL.ts @@ -243,6 +243,79 @@ export const plPL: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const plPL: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Skontaktuj się z administratorem swojej organizacji, aby rozszerzyć swoje uprawnienia.', @@ -680,6 +757,10 @@ export const plPL: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Niestandardowy dostawca SAML', google: undefined, diff --git a/packages/localizations/src/pt-BR.ts b/packages/localizations/src/pt-BR.ts index db52fe300a0..ee6e3fb2846 100644 --- a/packages/localizations/src/pt-BR.ts +++ b/packages/localizations/src/pt-BR.ts @@ -249,6 +249,79 @@ export const ptBR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const ptBR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Entre em contato com o administrador da sua organização para ampliar suas permissões.', @@ -686,6 +763,10 @@ export const ptBR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Provedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/pt-PT.ts b/packages/localizations/src/pt-PT.ts index cd17667f106..d0398db77a2 100644 --- a/packages/localizations/src/pt-PT.ts +++ b/packages/localizations/src/pt-PT.ts @@ -251,6 +251,79 @@ export const ptPT: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -635,6 +708,10 @@ export const ptPT: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contacte o administrador da sua organização para ampliar as suas permissões.', @@ -688,6 +765,10 @@ export const ptPT: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Fornecedor SAML personalizado', google: undefined, diff --git a/packages/localizations/src/ro-RO.ts b/packages/localizations/src/ro-RO.ts index 770217ef56f..f04ca27fc6c 100644 --- a/packages/localizations/src/ro-RO.ts +++ b/packages/localizations/src/ro-RO.ts @@ -249,6 +249,79 @@ export const roRO: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const roRO: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Contactați administratorul organizației dumneavoastră pentru a vă extinde permisiunile.', @@ -687,6 +764,10 @@ export const roRO: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Furnizor SAML personalizat', google: undefined, diff --git a/packages/localizations/src/ru-RU.ts b/packages/localizations/src/ru-RU.ts index 80a74813621..97005a6fbb0 100644 --- a/packages/localizations/src/ru-RU.ts +++ b/packages/localizations/src/ru-RU.ts @@ -243,6 +243,79 @@ export const ruRU: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const ruRU: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Обратитесь к администратору вашей организации, чтобы расширить ваши разрешения.', @@ -680,6 +757,10 @@ export const ruRU: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Пользовательский поставщик SAML', google: undefined, diff --git a/packages/localizations/src/sk-SK.ts b/packages/localizations/src/sk-SK.ts index 00d5dbb4db0..36814980eca 100644 --- a/packages/localizations/src/sk-SK.ts +++ b/packages/localizations/src/sk-SK.ts @@ -243,6 +243,79 @@ export const skSK: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const skSK: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontaktujte správcu vašej organizácie pre rozšírenie vašich oprávnení.', @@ -680,6 +757,10 @@ export const skSK: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Vlastný poskytovateľ SAML', google: undefined, diff --git a/packages/localizations/src/sr-RS.ts b/packages/localizations/src/sr-RS.ts index d3bde5446ab..c1b209b00f7 100644 --- a/packages/localizations/src/sr-RS.ts +++ b/packages/localizations/src/sr-RS.ts @@ -243,6 +243,79 @@ export const srRS: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const srRS: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontaktirajte administratora vaše organizacije da biste proširili svoje dozvole.', @@ -680,6 +757,10 @@ export const srRS: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Prilagođeni SAML provajder', google: undefined, diff --git a/packages/localizations/src/sv-SE.ts b/packages/localizations/src/sv-SE.ts index 9347df7a469..a94c14b64d4 100644 --- a/packages/localizations/src/sv-SE.ts +++ b/packages/localizations/src/sv-SE.ts @@ -243,6 +243,79 @@ export const svSE: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const svSE: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Kontakta administratören för din organisation för att utöka dina behörigheter.', @@ -680,6 +757,10 @@ export const svSE: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Anpassad SAML-leverantör', google: undefined, diff --git a/packages/localizations/src/ta-IN.ts b/packages/localizations/src/ta-IN.ts index deb81aea490..e7025ec6989 100644 --- a/packages/localizations/src/ta-IN.ts +++ b/packages/localizations/src/ta-IN.ts @@ -251,6 +251,79 @@ export const taIN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -635,6 +708,10 @@ export const taIN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'உங்கள் அனுமதிகளை மேம்படுத்த உங்கள் நிறுவனத்தின் நிர்வாகியைத் தொடர்பு கொள்ளவும்.', @@ -688,6 +765,10 @@ export const taIN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'தனிப்பயன் SAML வழங்குநர்', google: undefined, diff --git a/packages/localizations/src/te-IN.ts b/packages/localizations/src/te-IN.ts index 3370d5b1d4c..b7761190f76 100644 --- a/packages/localizations/src/te-IN.ts +++ b/packages/localizations/src/te-IN.ts @@ -250,6 +250,79 @@ export const teIN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -634,6 +707,10 @@ export const teIN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'మీ అనుమతులను అప్‌గ్రేడ్ చేయడానికి మీ సంస్థ నిర్వాహకుడిని సంప్రదించండి.', @@ -687,6 +764,10 @@ export const teIN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'కస్టమ్ SAML ప్రొవైడర్', google: undefined, diff --git a/packages/localizations/src/th-TH.ts b/packages/localizations/src/th-TH.ts index f3604cbf52f..d65b08fc356 100644 --- a/packages/localizations/src/th-TH.ts +++ b/packages/localizations/src/th-TH.ts @@ -247,6 +247,79 @@ export const thTH: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -631,6 +704,10 @@ export const thTH: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'ติดต่อผู้ดูแลระบบขององค์กรของคุณเพื่ออัปเกรดสิทธิ์ของคุณ', @@ -683,6 +760,10 @@ export const thTH: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'ผู้ให้บริการ SAML แบบกำหนดเอง', google: undefined, diff --git a/packages/localizations/src/tr-TR.ts b/packages/localizations/src/tr-TR.ts index 2e097ea1d5c..ad2223c7909 100644 --- a/packages/localizations/src/tr-TR.ts +++ b/packages/localizations/src/tr-TR.ts @@ -243,6 +243,79 @@ export const trTR: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const trTR: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'İzinlerinizi yükseltmek için organizasyonunuzun yöneticisiyle iletişime geçin.', @@ -680,6 +757,10 @@ export const trTR: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Özel SAML Sağlayıcısı', google: undefined, diff --git a/packages/localizations/src/uk-UA.ts b/packages/localizations/src/uk-UA.ts index 9401aeaa48c..f9fd91af731 100644 --- a/packages/localizations/src/uk-UA.ts +++ b/packages/localizations/src/uk-UA.ts @@ -243,6 +243,79 @@ export const ukUA: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const ukUA: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Зверніться до адміністратора вашої організації, щоб розширити ваші дозволи.', @@ -680,6 +757,10 @@ export const ukUA: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Користувацький постачальник SAML', google: undefined, diff --git a/packages/localizations/src/vi-VN.ts b/packages/localizations/src/vi-VN.ts index 7a1f375f3ad..c21e80d0184 100644 --- a/packages/localizations/src/vi-VN.ts +++ b/packages/localizations/src/vi-VN.ts @@ -249,6 +249,79 @@ export const viVN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -633,6 +706,10 @@ export const viVN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: 'Liên hệ với quản trị viên tổ chức của bạn để nâng cấp quyền của bạn.', @@ -686,6 +763,10 @@ export const viVN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: 'Nhà cung cấp SAML tùy chỉnh', google: undefined, diff --git a/packages/localizations/src/zh-CN.ts b/packages/localizations/src/zh-CN.ts index f4d6a3bd447..5d02a382dd5 100644 --- a/packages/localizations/src/zh-CN.ts +++ b/packages/localizations/src/zh-CN.ts @@ -243,6 +243,79 @@ export const zhCN: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -627,6 +700,10 @@ export const zhCN: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: '请联系您的组织管理员以升级您的权限。', @@ -679,6 +756,10 @@ export const zhCN: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: '自定义 SAML 提供商', google: undefined, diff --git a/packages/localizations/src/zh-TW.ts b/packages/localizations/src/zh-TW.ts index 2ca1facbad5..713b1080c45 100644 --- a/packages/localizations/src/zh-TW.ts +++ b/packages/localizations/src/zh-TW.ts @@ -246,6 +246,79 @@ export const zhTW: LocalizationResource = { required: undefined, }, }, + oidcCustom: { + credentialsStep: { + clientId: { + label: undefined, + placeholder: undefined, + }, + clientSecret: { + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + paragraph: undefined, + }, + endpointsStep: { + discoveryUrl: { + description: undefined, + label: undefined, + placeholder: undefined, + }, + headerSubtitle: undefined, + manual: { + authUrl: { + label: undefined, + placeholder: undefined, + }, + description: undefined, + tokenUrl: { + label: undefined, + placeholder: undefined, + }, + userInfoUrl: { + label: undefined, + placeholder: undefined, + }, + }, + modes: { + ariaLabel: undefined, + discoveryUrl: undefined, + manual: undefined, + }, + }, + mainHeaderTitle: undefined, + redirectUriStep: { + claims: { + description: undefined, + table: { + columns: { + attribute: undefined, + claim: undefined, + }, + rows: { + email: { + attribute: undefined, + }, + firstName: { + attribute: undefined, + }, + lastName: { + attribute: undefined, + }, + subject: { + attribute: undefined, + }, + }, + }, + }, + headerSubtitle: undefined, + paragraph: undefined, + redirectUri: { + label: undefined, + }, + }, + }, samlCustom: { assignUsersStep: { headerSubtitle: undefined, @@ -630,6 +703,10 @@ export const zhTW: LocalizationResource = { }, mainHeaderTitle: undefined, }, + unsupportedProvider: { + description: undefined, + title: undefined, + }, }, missingManageEnterpriseConnectionsPermission: { subtitle: '請聯絡您的組織管理員以升級您的權限。', @@ -682,6 +759,10 @@ export const zhTW: LocalizationResource = { title: undefined, }, selectProviderStep: { + oidc: { + groupLabel: undefined, + oidcProvider: undefined, + }, saml: { customSaml: '自訂 SAML 提供者', google: undefined, diff --git a/packages/shared/src/types/elementIds.ts b/packages/shared/src/types/elementIds.ts index b685d908db7..6975892a769 100644 --- a/packages/shared/src/types/elementIds.ts +++ b/packages/shared/src/types/elementIds.ts @@ -31,6 +31,13 @@ export type FieldId = | 'idpMetadata' | 'idpMetadataUrl' | 'idpSsoUrl' + | 'discoveryUrl' + | 'authUrl' + | 'tokenUrl' + | 'userInfoUrl' + | 'clientId' + | 'clientSecret' + | 'redirectUri' | 'acsUrl' | 'spEntityId' | 'web3WalletName' diff --git a/packages/shared/src/types/enterpriseConnection.ts b/packages/shared/src/types/enterpriseConnection.ts index f3e17fc9367..ed5c59eaa4d 100644 --- a/packages/shared/src/types/enterpriseConnection.ts +++ b/packages/shared/src/types/enterpriseConnection.ts @@ -100,7 +100,11 @@ export interface EnterpriseOAuthConfigJSON { name: string; provider_key?: string; client_id: string; + redirect_uri?: string; discovery_url?: string; + auth_url?: string; + token_url?: string; + user_info_url?: string; logo_public_url?: string | null; requires_pkce?: boolean; created_at: number; @@ -112,7 +116,11 @@ export interface EnterpriseOAuthConfigResource { name: string; clientId: string; providerKey?: string; + redirectUri?: string; discoveryUrl?: string; + authUrl?: string; + tokenUrl?: string; + userInfoUrl?: string; logoPublicUrl?: string | null; requiresPkce?: boolean; createdAt: Date | null; diff --git a/packages/shared/src/types/localization.ts b/packages/shared/src/types/localization.ts index b4ac66d3d2c..d73ed179a04 100644 --- a/packages/shared/src/types/localization.ts +++ b/packages/shared/src/types/localization.ts @@ -1404,6 +1404,10 @@ export type __internal_LocalizationResource = { google: LocalizationValue; microsoft: LocalizationValue; }; + oidc: { + groupLabel: LocalizationValue; + oidcProvider: LocalizationValue; + }; warning: LocalizationValue; }; changeProviderDialog: { @@ -1522,6 +1526,75 @@ export type __internal_LocalizationResource = { title: LocalizationValue; dismiss: LocalizationValue; }; + oidcCustom: { + mainHeaderTitle: LocalizationValue; + redirectUriStep: { + headerSubtitle: LocalizationValue; + paragraph: LocalizationValue; + claims: { + description: LocalizationValue; + table: { + columns: { + attribute: LocalizationValue; + claim: LocalizationValue; + }; + rows: { + email: { attribute: LocalizationValue }; + firstName: { attribute: LocalizationValue }; + lastName: { attribute: LocalizationValue }; + subject: { attribute: LocalizationValue }; + }; + }; + }; + redirectUri: { + label: LocalizationValue; + }; + }; + endpointsStep: { + headerSubtitle: LocalizationValue; + discoveryUrl: { + description: LocalizationValue; + label: LocalizationValue; + placeholder: LocalizationValue; + }; + manual: { + authUrl: { + label: LocalizationValue; + placeholder: LocalizationValue; + }; + description: LocalizationValue; + tokenUrl: { + label: LocalizationValue; + placeholder: LocalizationValue; + }; + userInfoUrl: { + label: LocalizationValue; + placeholder: LocalizationValue; + }; + }; + modes: { + ariaLabel: LocalizationValue; + discoveryUrl: LocalizationValue; + manual: LocalizationValue; + }; + }; + credentialsStep: { + headerSubtitle: LocalizationValue; + clientId: { + label: LocalizationValue; + placeholder: LocalizationValue; + }; + clientSecret: { + label: LocalizationValue; + placeholder: LocalizationValue; + }; + paragraph: LocalizationValue; + }; + }; + unsupportedProvider: { + title: LocalizationValue; + description: LocalizationValue; + }; samlOkta: { mainHeaderTitle: LocalizationValue; createAppStep: { diff --git a/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts b/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts index a0189c74311..3b424285b7c 100644 --- a/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts +++ b/packages/ui/src/components/ConfigureSSO/domain/__tests__/organizationEnterpriseConnection.test.ts @@ -1,6 +1,7 @@ import type { EmailAddressResource, EnterpriseConnectionResource, + EnterpriseOAuthConfigResource, OrganizationDomainResource, SamlAccountConnectionResource, UserResource, @@ -24,6 +25,14 @@ const makeSamlConnection = (overrides: Partial = ...overrides, }) as SamlAccountConnectionResource; +const makeOauthConfig = (overrides: Partial = {}): EnterpriseOAuthConfigResource => + ({ + id: 'oauth_1', + name: 'oidc', + clientId: '', + ...overrides, + }) as EnterpriseOAuthConfigResource; + const makeConnection = (overrides: Partial = {}): EnterpriseConnectionResource => ({ id: 'enc_1', @@ -49,6 +58,14 @@ const fullyConfiguredSaml = makeSamlConnection({ idpMetadataUrl: 'https://idp.example.com/metadata', }); +const configuredOidc = makeOauthConfig({ + clientId: 'client_abc', + discoveryUrl: 'https://idp.example.com/.well-known/openid-configuration', +}); + +const makeOidcConnection = (overrides: Partial = {}): EnterpriseConnectionResource => + makeConnection({ provider: 'oauth_custom_acme', samlConnection: null, oauthConfig: configuredOidc, ...overrides }); + // Builds the entity with sensible defaults; each test overrides what it cares // about. const derive = (overrides: Partial[0]> = {}) => @@ -79,6 +96,11 @@ describe('organizationEnterpriseConnection', () => { it('connection → its provider', () => { expect(derive({ connection: makeConnection({ provider: 'saml_custom' }) }).provider).toBe('saml_custom'); }); + it('carries a custom OIDC key verbatim', () => { + expect(derive({ connection: makeConnection({ provider: 'oauth_custom_clerk_dev' }) }).provider).toBe( + 'oauth_custom_clerk_dev', + ); + }); }); describe('isActive', () => { @@ -122,6 +144,36 @@ describe('organizationEnterpriseConnection', () => { }).hasMinimumConfiguration, ).toBe(false); }); + it('oidc client id and discovery URL present → true', () => { + expect(derive({ connection: makeOidcConnection() }).hasMinimumConfiguration).toBe(true); + }); + it('oidc client id without endpoints → false', () => { + expect( + derive({ connection: makeOidcConnection({ oauthConfig: makeOauthConfig({ clientId: 'client_abc' }) }) }) + .hasMinimumConfiguration, + ).toBe(false); + }); + it('oidc client id with manual authorization and token URLs → true', () => { + expect( + derive({ + connection: makeOidcConnection({ + oauthConfig: makeOauthConfig({ + clientId: 'client_abc', + authUrl: 'https://idp.example.com/authorize', + tokenUrl: 'https://idp.example.com/token', + }), + }), + }).hasMinimumConfiguration, + ).toBe(true); + }); + it('oidc without oauth config → false', () => { + expect(derive({ connection: makeOidcConnection({ oauthConfig: null }) }).hasMinimumConfiguration).toBe(false); + }); + it('oidc with empty client id → false', () => { + expect( + derive({ connection: makeOidcConnection({ oauthConfig: makeOauthConfig() }) }).hasMinimumConfiguration, + ).toBe(false); + }); }); describe('hasSuccessfulTestRun', () => { @@ -197,6 +249,17 @@ describe('organizationEnterpriseConnection', () => { }).status, ).toBe('active'); }); + it('oidc configured + successfully tested + not active → inactive', () => { + expect( + derive({ + connection: makeOidcConnection({ active: false }), + hasSuccessfulTestRun: true, + }).status, + ).toBe('inactive'); + }); + it('active oidc connection → active', () => { + expect(derive({ connection: makeOidcConnection({ active: true }) }).status).toBe('active'); + }); }); it('is pure: identical inputs produce a deep-equal entity', () => { @@ -247,10 +310,57 @@ describe('isEnterpriseConnectionConfigured', () => { it('idpSsoUrl + idpEntityId present → true', () => { expect(isEnterpriseConnectionConfigured(makeConnection({ samlConnection: fullyConfiguredSaml }))).toBe(true); }); + it('oidc with no oauth config → false', () => { + expect(isEnterpriseConnectionConfigured(makeOidcConnection({ oauthConfig: null }))).toBe(false); + }); + it('oidc with empty client id → false', () => { + expect(isEnterpriseConnectionConfigured(makeOidcConnection({ oauthConfig: makeOauthConfig() }))).toBe(false); + }); + it('oidc with client id and discovery URL present → true', () => { + expect(isEnterpriseConnectionConfigured(makeOidcConnection())).toBe(true); + }); + it('oidc with client id but no endpoints → false', () => { + expect( + isEnterpriseConnectionConfigured( + makeOidcConnection({ oauthConfig: makeOauthConfig({ clientId: 'client_abc' }) }), + ), + ).toBe(false); + }); + it('oidc with client id and manual authorization and token URLs → true', () => { + expect( + isEnterpriseConnectionConfigured( + makeOidcConnection({ + oauthConfig: makeOauthConfig({ + clientId: 'client_abc', + authUrl: 'https://idp.example.com/authorize', + tokenUrl: 'https://idp.example.com/token', + }), + }), + ), + ).toBe(true); + }); + it('branches on provider: an oidc connection is not satisfied by saml fields', () => { + expect( + isEnterpriseConnectionConfigured( + makeOidcConnection({ oauthConfig: makeOauthConfig(), samlConnection: fullyConfiguredSaml }), + ), + ).toBe(false); + }); + it('branches on provider: a saml connection is not satisfied by oauth fields', () => { + expect( + isEnterpriseConnectionConfigured( + makeConnection({ provider: 'saml_okta', samlConnection: null, oauthConfig: configuredOidc }), + ), + ).toBe(false); + }); it('matches the derived `hasMinimumConfiguration` field', () => { const connection = makeConnection({ samlConnection: fullyConfiguredSaml }); expect(isEnterpriseConnectionConfigured(connection)).toBe(derive({ connection }).hasMinimumConfiguration); }); + it('matches the derived `hasMinimumConfiguration` field for oidc', () => { + const connection = makeOidcConnection(); + expect(isEnterpriseConnectionConfigured(connection)).toBe(derive({ connection }).hasMinimumConfiguration); + }); }); describe('areAllOrganizationDomainsVerified', () => { diff --git a/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts b/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts index fd9f7c7bd56..fa4baeb775f 100644 --- a/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts +++ b/packages/ui/src/components/ConfigureSSO/domain/organizationEnterpriseConnection.ts @@ -5,7 +5,10 @@ import type { UserResource, } from '@clerk/shared/types'; -import type { ProviderType } from '../types'; +import type { EnterpriseConnectionProviderType, OidcProviderType } from '../types'; + +export const isOidcProvider = (provider: string): provider is OidcProviderType => + provider.startsWith('oidc_') || provider.startsWith('oauth_custom_'); /** * The email whose domain backs the connection: the user's primary address if @@ -40,7 +43,7 @@ export type OrganizationEnterpriseConnectionStatus = 'unconfigured' | 'in_progre * object the wizard makes every flow decision from. A snapshot of flattened booleans/values. */ export interface OrganizationEnterpriseConnection { - readonly provider: ProviderType | undefined; + readonly provider: EnterpriseConnectionProviderType | undefined; readonly hasConnection: boolean; readonly isActive: boolean; readonly hasMinimumConfiguration: boolean; @@ -48,10 +51,20 @@ export interface OrganizationEnterpriseConnection { readonly status: OrganizationEnterpriseConnectionStatus; } -// TODO - Update to support OpenID Connect export const isEnterpriseConnectionConfigured = ( connection: EnterpriseConnectionResource | null | undefined, -): boolean => Boolean(connection?.samlConnection?.idpSsoUrl && connection?.samlConnection?.idpEntityId); +): boolean => { + if (!connection) { + return false; + } + if (isOidcProvider(connection.provider)) { + const oauthConfig = connection.oauthConfig; + return Boolean( + oauthConfig?.clientId && (oauthConfig.discoveryUrl || (oauthConfig.authUrl && oauthConfig.tokenUrl)), + ); + } + return Boolean(connection.samlConnection?.idpSsoUrl && connection.samlConnection?.idpEntityId); +}; export const areAllOrganizationDomainsVerified = (domains: OrganizationDomainResource[] | null | undefined): boolean => !!domains?.length && domains.every(domain => domain.ownershipVerification?.status === 'verified'); @@ -86,7 +99,7 @@ export const organizationEnterpriseConnection = ({ const hasMinimumConfiguration = isEnterpriseConnectionConfigured(connection); return { - provider: connection?.provider as ProviderType | undefined, + provider: connection?.provider as EnterpriseConnectionProviderType | undefined, hasConnection, isActive, hasMinimumConfiguration, diff --git a/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx b/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx index bb9579ad215..5288dd01549 100644 --- a/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx +++ b/packages/ui/src/components/ConfigureSSO/hooks/__tests__/useOrganizationEnterpriseConnection.test.tsx @@ -7,20 +7,22 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; // test-runs query's `enabled` and folds its loading into the global gate. // A connection shaped enough for the umbrella's gating: the derived -// "configured" predicate reads `samlConnection.idpSsoUrl` + `idpEntityId`, and -// the active path reads `active`. +// "configured" predicate branches on `provider`, then reads +// `samlConnection.idpSsoUrl` + `idpEntityId`, and the active path reads `active`. type MockConnection = { id: string; + provider: string; active?: boolean; samlConnection?: { idpSsoUrl?: string; idpEntityId?: string } | null; }; const configuredConnection = (id: string): MockConnection => ({ id, + provider: 'saml_okta', samlConnection: { idpSsoUrl: 'https://idp.example.com/sso', idpEntityId: 'https://idp.example.com/entity' }, }); -const unconfiguredConnection = (id: string): MockConnection => ({ id, samlConnection: null }); +const unconfiguredConnection = (id: string): MockConnection => ({ id, provider: 'saml_okta', samlConnection: null }); // Mutable state the connection-source mock reads from, so a test can flip from // "no connection at load" to "connection created mid-flow" between renders. @@ -119,7 +121,7 @@ describe('useOrganizationEnterpriseConnection — test-runs gating', () => { }); it('(a2) active (but unconfigured) connection at load → test-runs active via the isActive path', () => { - connectionsState.data = [{ id: 'ent_active', active: true, samlConnection: null }]; + connectionsState.data = [{ id: 'ent_active', provider: 'saml_okta', active: true, samlConnection: null }]; const { result } = renderHook(() => useOrganizationEnterpriseConnection()); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/__tests__/ConfigureStep.test.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/__tests__/ConfigureStep.test.tsx new file mode 100644 index 00000000000..13288278cd1 --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/__tests__/ConfigureStep.test.tsx @@ -0,0 +1,483 @@ +import { ClerkAPIResponseError } from '@clerk/shared/error'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { Flow } from '@/customizables'; +import { bindCreateFixtures } from '@/test/create-fixtures'; +import { render, screen } from '@/test/utils'; +import { CardStateProvider, useCardState } from '@/ui/elements/contexts'; + +import type { EnterpriseConnectionProviderType } from '../../../types'; +import { Wizard } from '../../../elements/Wizard'; + +// The dispatch reads `organizationEnterpriseConnection.provider`. The nested +// sub-flows also read `enterpriseConnection` (via `Step.Footer.Reset`), which is +// left undefined so that footer self-hides in this isolated render. +const contextState = vi.hoisted(() => ({ + provider: undefined as string | undefined, + isOIDCFlowEnabled: true, + enterpriseConnection: undefined as + | { + id: string; + oauthConfig: { + redirectUri?: string; + discoveryUrl?: string; + authUrl?: string; + tokenUrl?: string; + userInfoUrl?: string; + } | null; + } + | undefined, +})); +const updateConnection = vi.hoisted(() => vi.fn()); + +const CardErrorProbe = () => { + const { error } = useCardState(); + + return error ?
{error}
: null; +}; + +vi.mock('../../../ConfigureSSOContext', () => ({ + useConfigureSSO: () => ({ + enterpriseConnection: contextState.enterpriseConnection, + contentRef: { current: null }, + enterpriseConnectionMutations: { updateConnection }, + organizationEnterpriseConnection: { + provider: contextState.provider, + hasConnection: true, + }, + isOIDCFlowEnabled: contextState.isOIDCFlowEnabled, + }), +})); + +import { ConfigureProviderStep, resolveConfigureSteps } from '../index'; +import { OidcCustomConfigureSteps } from '../oidc'; +import { OidcCredentialsStep } from '../oidc/shared/OidcCredentialsStep'; +import { + SamlCustomConfigureSteps, + SamlGoogleConfigureSteps, + SamlMicrosoftConfigureSteps, + SamlOktaConfigureSteps, +} from '../saml'; + +const { createFixtures } = bindCreateFixtures('ConfigureSSO'); + +describe('resolveConfigureSteps', () => { + it('dispatches custom and legacy OIDC provider keys to the OIDC sub-flow', () => { + expect(resolveConfigureSteps('oauth_custom_clerk_dev', true)).toBe(OidcCustomConfigureSteps); + expect(resolveConfigureSteps('oidc_clerk_dev', true)).toBe(OidcCustomConfigureSteps); + expect(resolveConfigureSteps('oidc_ghe_acme', true)).toBe(OidcCustomConfigureSteps); + expect(resolveConfigureSteps('oidc_gitlab_ent_acme', true)).toBe(OidcCustomConfigureSteps); + expect(resolveConfigureSteps('oidc_custom', true)).toBe(OidcCustomConfigureSteps); + }); + + it('does not dispatch OIDC providers while the experimental flow is disabled', () => { + expect(resolveConfigureSteps('oauth_custom_clerk_dev', false)).toBeUndefined(); + expect(resolveConfigureSteps('oidc_clerk_dev', false)).toBeUndefined(); + }); + + it('dispatches SAML providers by exact literal', () => { + expect(resolveConfigureSteps('saml_okta', false)).toBe(SamlOktaConfigureSteps); + expect(resolveConfigureSteps('saml_custom', false)).toBe(SamlCustomConfigureSteps); + expect(resolveConfigureSteps('saml_google', false)).toBe(SamlGoogleConfigureSteps); + expect(resolveConfigureSteps('saml_microsoft', false)).toBe(SamlMicrosoftConfigureSteps); + }); + + it('returns undefined for an unrecognized provider so the caller can degrade', () => { + expect(resolveConfigureSteps('ldap_enterprise' as EnterpriseConnectionProviderType, true)).toBeUndefined(); + }); +}); + +describe('ConfigureProviderStep', () => { + beforeEach(() => { + contextState.provider = undefined; + contextState.isOIDCFlowEnabled = true; + contextState.enterpriseConnection = undefined; + updateConnection.mockReset(); + }); + + const renderStep = (wrapper: React.ComponentType<{ children?: React.ReactNode }>) => + render( + + + + + + , + { wrapper }, + ); + + const renderCredentialsStep = (wrapper: React.ComponentType<{ children?: React.ReactNode }>) => + render( + + + + + + + + + , + { wrapper }, + ); + + it('renders the OIDC configure steps for a custom OAuth provider key without throwing', async () => { + contextState.provider = 'oauth_custom_clerk_dev'; + contextState.enterpriseConnection = { + id: 'ent_123', + oauthConfig: { + redirectUri: 'https://instance.example/v1/oauth_callback', + }, + }; + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + expect(await screen.findAllByText(/create a new oidc application/i)).not.toHaveLength(0); + const redirectUri = screen.getByRole('textbox', { name: 'Authorized redirect URI' }); + expect(redirectUri).toHaveAttribute('readonly'); + expect(redirectUri).toHaveValue('https://instance.example/v1/oauth_callback'); + expect(screen.getByText('Ensure your ID token includes the following claims:')).toBeInTheDocument(); + expect(screen.getByRole('table')).toBeInTheDocument(); + expect(screen.getAllByRole('row')).toHaveLength(5); + expect(screen.getByText('sub')).toBeInTheDocument(); + expect(screen.getByText('email')).toBeInTheDocument(); + expect(screen.getByRole('columnheader', { name: 'ID token claim' })).toBeInTheDocument(); + expect(screen.getByText('given_name')).toBeInTheDocument(); + expect(screen.getByText('family_name')).toBeInTheDocument(); + + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + const discoveryMode = await screen.findByRole('radio', { name: 'Add via discovery endpoint' }); + const manualMode = screen.getByRole('radio', { name: 'Configure manually' }); + expect(discoveryMode).toBeChecked(); + expect(screen.getAllByRole('textbox')).toHaveLength(1); + expect(screen.getByRole('button', { name: 'Continue' })).toBeDisabled(); + + await userEvent.click(manualMode); + + expect(screen.getAllByRole('textbox')).toHaveLength(3); + }); + + it('saves the discovery endpoint before advancing to credentials', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockReset(); + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + await userEvent.type( + screen.getByRole('textbox', { name: 'Discovery endpoint' }), + 'https://idp.example/.well-known/openid-configuration', + ); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(updateConnection).toHaveBeenCalledWith('ent_123', { + oidc: { discoveryUrl: 'https://idp.example/.well-known/openid-configuration' }, + }); + }); + }); + + it('saves manual endpoints before advancing to credentials', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockReset(); + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + const manualMode = await screen.findByRole('radio', { name: 'Configure manually' }); + await userEvent.click(manualMode); + + const authUrl = screen.getByRole('textbox', { name: 'Authorization URL' }); + const tokenUrl = screen.getByRole('textbox', { name: 'Token URL' }); + const userInfoUrl = screen.getByRole('textbox', { name: 'User Info URL' }); + await userEvent.type(authUrl, 'https://idp.example/authorize'); + await userEvent.type(tokenUrl, 'https://idp.example/token'); + await userEvent.type(userInfoUrl, 'https://idp.example/userinfo'); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(updateConnection).toHaveBeenCalledWith('ent_123', { + oidc: { + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }); + }); + }); + + it('saves manual endpoints without a user info URL', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockReset(); + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + const manualMode = await screen.findByRole('radio', { name: 'Configure manually' }); + await userEvent.click(manualMode); + + const authUrl = screen.getByRole('textbox', { name: 'Authorization URL' }); + const tokenUrl = screen.getByRole('textbox', { name: 'Token URL' }); + await userEvent.type(authUrl, 'https://idp.example/authorize'); + await userEvent.type(tokenUrl, 'https://idp.example/token'); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(updateConnection).toHaveBeenCalledWith('ent_123', { + oidc: { + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: '', + }, + }); + }); + }); + + it('clears endpoint API errors when switching configuration modes', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockRejectedValueOnce( + new ClerkAPIResponseError('Error', { + data: [ + { + code: 'form_param_invalid', + long_message: 'The endpoint configuration is invalid.', + message: 'The endpoint configuration is invalid.', + }, + ], + status: 422, + }), + ); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + await userEvent.type(screen.getByRole('textbox', { name: 'Discovery endpoint' }), 'https://idp.example/discovery'); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + expect(await screen.findByText('The endpoint configuration is invalid.')).toBeInTheDocument(); + + await userEvent.click(screen.getByRole('radio', { name: 'Configure manually' })); + + expect(screen.queryByText('The endpoint configuration is invalid.')).not.toBeInTheDocument(); + }); + + it('saves credentials before advancing', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockReset(); + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + await userEvent.type( + screen.getByRole('textbox', { name: 'Discovery endpoint' }), + 'https://idp.example/.well-known/openid-configuration', + ); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + const clientId = await screen.findByRole('textbox', { name: 'Client ID' }); + const clientSecret = screen.getByLabelText('Client secret'); + await userEvent.type(clientId, 'client_123'); + await userEvent.type(clientSecret, 'secret_456'); + + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(updateConnection).toHaveBeenLastCalledWith('ent_123', { + oidc: { clientId: 'client_123', clientSecret: 'secret_456' }, + }); + }); + }); + + it('preserves manual endpoints while saving credentials', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { + id: 'ent_123', + oauthConfig: { + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }; + updateConnection.mockReset(); + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + const clientId = await screen.findByRole('textbox', { name: 'Client ID' }); + const clientSecret = screen.getByLabelText('Client secret'); + await userEvent.type(clientId, 'client_123'); + await userEvent.type(clientSecret, 'secret_456'); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(updateConnection).toHaveBeenLastCalledWith('ent_123', { + oidc: { + clientId: 'client_123', + clientSecret: 'secret_456', + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }); + }); + }); + + it('displays credential API errors on their matching fields', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { id: 'ent_123', oauthConfig: null }; + updateConnection.mockReset(); + updateConnection.mockRejectedValue( + new ClerkAPIResponseError('Error', { + data: [ + { + code: 'form_param_invalid', + long_message: 'Client ID is invalid.', + message: 'Client ID is invalid.', + meta: { param_name: 'client_id' }, + }, + { + code: 'form_param_invalid', + long_message: 'Client secret is invalid.', + message: 'Client secret is invalid.', + meta: { param_name: 'client_secret' }, + }, + ], + status: 422, + }), + ); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderCredentialsStep(wrapper); + + const clientId = screen.getByRole('textbox'); + const clientSecret = document.querySelector('input[name="clientSecret"]'); + expect(clientSecret).not.toBeNull(); + await userEvent.type(clientId, 'client_123'); + await userEvent.type(clientSecret!, 'secret_456'); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await vi.waitFor(() => { + expect(document.getElementById('error-clientId')).toHaveTextContent('Client ID is invalid.'); + expect(document.getElementById('error-clientSecret')).toHaveTextContent('Client secret is invalid.'); + expect(clientId).toHaveAttribute('aria-describedby', 'error-clientId'); + expect(clientSecret).toHaveAttribute('aria-describedby', 'error-clientSecret'); + }); + }); + + it('selects manual mode when an existing connection has manual endpoints without a discovery URL', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { + id: 'ent_123', + oauthConfig: { + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }; + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + + const discoveryMode = await screen.findByRole('radio', { name: 'Add via discovery endpoint' }); + const manualMode = screen.getByRole('radio', { name: 'Configure manually' }); + expect(discoveryMode).not.toBeChecked(); + expect(manualMode).toBeChecked(); + expect(screen.getByRole('textbox', { name: 'Authorization URL' })).toHaveValue('https://idp.example/authorize'); + }); + + it('populates manual endpoints resolved from discovery', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { + id: 'ent_123', + oauthConfig: { + discoveryUrl: 'https://idp.example/.well-known/openid-configuration', + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }; + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + const manualMode = await screen.findByRole('radio', { name: 'Configure manually' }); + await userEvent.click(manualMode); + + expect(screen.getByRole('textbox', { name: 'Authorization URL' })).toHaveValue('https://idp.example/authorize'); + expect(screen.getByRole('textbox', { name: 'Token URL' })).toHaveValue('https://idp.example/token'); + expect(screen.getByRole('textbox', { name: 'User Info URL' })).toHaveValue('https://idp.example/userinfo'); + }); + + it('retains manual mode when returning from credentials with a stale discovery URL', async () => { + contextState.provider = 'oidc_clerk_dev'; + contextState.enterpriseConnection = { + id: 'ent_123', + oauthConfig: { + discoveryUrl: 'https://idp.example/.well-known/openid-configuration', + authUrl: 'https://idp.example/authorize', + tokenUrl: 'https://idp.example/token', + userInfoUrl: 'https://idp.example/userinfo', + }, + }; + updateConnection.mockResolvedValue({}); + const { wrapper } = await createFixtures(); + + const { userEvent } = renderStep(wrapper); + + await userEvent.click(await screen.findByRole('button', { name: 'Continue' })); + const manualMode = await screen.findByRole('radio', { name: 'Configure manually' }); + await userEvent.click(manualMode); + await userEvent.click(screen.getByRole('button', { name: 'Continue' })); + + await screen.findByRole('textbox', { name: 'Client ID' }); + await userEvent.click(screen.getByRole('button', { name: 'Previous' })); + + expect(await screen.findByRole('radio', { name: 'Configure manually' })).toBeChecked(); + expect(screen.getByRole('textbox', { name: 'Authorization URL' })).toHaveValue('https://idp.example/authorize'); + }); + + it('degrades to the unsupported-provider state for a provider the SDK does not recognize', async () => { + contextState.provider = 'ldap_enterprise'; + const { wrapper } = await createFixtures(); + + renderStep(wrapper); + + expect(await screen.findByText(/unsupported provider/i)).toBeInTheDocument(); + }); + + it('degrades to the unsupported-provider state for an existing OIDC connection when the flag is off', async () => { + contextState.provider = 'oauth_custom_clerk_dev'; + contextState.isOIDCFlowEnabled = false; + const { wrapper } = await createFixtures(); + + renderStep(wrapper); + + expect(await screen.findByText(/unsupported provider/i)).toBeInTheDocument(); + expect(screen.queryByText(/create a new oidc application/i)).not.toBeInTheDocument(); + }); +}); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx index b5f442e7bd5..6abf3e61005 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/index.tsx @@ -1,13 +1,15 @@ import React, { type JSX } from 'react'; -import { descriptors, Flow } from '@/customizables'; +import { descriptors, Flow, localizationKeys } from '@/customizables'; import { CardStateProvider } from '@/elements/contexts'; import { useConfigureSSO } from '../../ConfigureSSOContext'; +import { isOidcProvider } from '../../domain/organizationEnterpriseConnection'; import { Step } from '../../elements/Step'; import { useWizard, Wizard, type WizardStepConfig } from '../../elements/Wizard'; -import type { ProviderType } from '../../types'; +import type { EnterpriseConnectionProviderType, SamlProviderType } from '../../types'; import { SelectProviderStep } from '../SelectProviderStep'; +import { OidcCustomConfigureSteps } from './oidc'; import { SamlCustomConfigureSteps, SamlGoogleConfigureSteps, @@ -15,13 +17,25 @@ import { SamlOktaConfigureSteps, } from './saml'; -const STEPS_BY_PROVIDER: Record JSX.Element> = { +type ConfigureStepsComponent = () => JSX.Element; + +const STEPS_BY_SAML_PROVIDER: Record = { saml_custom: SamlCustomConfigureSteps, saml_okta: SamlOktaConfigureSteps, saml_google: SamlGoogleConfigureSteps, saml_microsoft: SamlMicrosoftConfigureSteps, }; +export const resolveConfigureSteps = ( + provider: EnterpriseConnectionProviderType, + isOIDCFlowEnabled: boolean, +): ConfigureStepsComponent | undefined => { + if (isOidcProvider(provider)) { + return isOIDCFlowEnabled ? OidcCustomConfigureSteps : undefined; + } + return STEPS_BY_SAML_PROVIDER[provider]; +}; + export const ConfigureStep = (): JSX.Element => { const { organizationEnterpriseConnection: c } = useConfigureSSO(); const { direction } = useWizard(); @@ -53,20 +67,14 @@ export const ConfigureStep = (): JSX.Element => { ); }; -const ConfigureProviderStep = (): JSX.Element | null => { - const { organizationEnterpriseConnection: c } = useConfigureSSO(); +export const ConfigureProviderStep = (): JSX.Element | null => { + const { organizationEnterpriseConnection: c, isOIDCFlowEnabled } = useConfigureSSO(); - // Type guard: the provider should be defined by the time we reach configure. if (!c.provider) { return null; } - // Adding a provider to the select step without a mapping here fails the build. - const StepsByProvider = STEPS_BY_PROVIDER[c.provider]; - - if (!StepsByProvider) { - throw new Error(`No steps found for provider: ${c.provider}`); - } + const ConfigureSteps = resolveConfigureSteps(c.provider, isOIDCFlowEnabled); return ( @@ -74,7 +82,17 @@ const ConfigureProviderStep = (): JSX.Element | null => { elementDescriptor={descriptors.configureSSOStep} elementId={descriptors.configureSSOStep.setId('configure')} > - + {ConfigureSteps ? ( + + ) : ( + <> + + + + )} ); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/OidcCustomConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/OidcCustomConfigureSteps.tsx new file mode 100644 index 00000000000..1e07e27f6ad --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/OidcCustomConfigureSteps.tsx @@ -0,0 +1,41 @@ +import { type JSX, useState } from 'react'; + +import { useConfigureSSO } from '../../../ConfigureSSOContext'; +import { Wizard, type WizardStepConfig } from '../../../elements/Wizard'; +import type { OidcIdpConfigurationMode } from '../shared/IdentityProviderConfigurationModes'; +import { OidcCredentialsStep } from './shared/OidcCredentialsStep'; +import { OidcEndpointsStep } from './shared/OidcEndpointsStep'; +import { OidcRedirectUriStep } from './shared/OidcRedirectUriStep'; + +const OIDC_STEPS: WizardStepConfig[] = [{ id: 'redirect-uri' }, { id: 'endpoints' }, { id: 'credentials' }]; + +export const OidcCustomConfigureSteps = (): JSX.Element => { + const { enterpriseConnection } = useConfigureSSO(); + const oauthConfig = enterpriseConnection?.oauthConfig; + // Keep mode outside the step so it persists across wizard navigation. + const [endpointMode, setEndpointMode] = useState( + oauthConfig?.authUrl && !oauthConfig.discoveryUrl ? 'manual' : 'discoveryUrl', + ); + + return ( + + + + + + + + + + + + + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/index.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/index.tsx new file mode 100644 index 00000000000..cd97ad4a843 --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/index.tsx @@ -0,0 +1 @@ +export { OidcCustomConfigureSteps } from './OidcCustomConfigureSteps'; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcCredentialsStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcCredentialsStep.tsx new file mode 100644 index 00000000000..27aa765ed7e --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcCredentialsStep.tsx @@ -0,0 +1,120 @@ +import React, { type JSX } from 'react'; + +import { localizationKeys, Text } from '@/customizables'; +import { useCardState } from '@/elements/contexts'; +import { Form } from '@/elements/Form'; +import { useFormControl } from '@/ui/utils/useFormControl'; +import { handleError } from '@/utils/errorHandler'; + +import { useConfigureSSO } from '../../../../ConfigureSSOContext'; +import { Step } from '../../../../elements/Step'; +import { useWizard } from '../../../../elements/Wizard'; +import { InnerStepCounter } from '../../../../elements/Wizard/InnerStepCounter'; +import { ActiveConnectionAlert } from '../../shared/ActiveConnectionAlert'; +import type { OidcIdpConfigurationMode } from '../../shared/IdentityProviderConfigurationModes'; + +interface OidcCredentialsStepProps { + mode: OidcIdpConfigurationMode; +} + +export const OidcCredentialsStep = ({ mode }: OidcCredentialsStepProps): JSX.Element => { + const card = useCardState(); + const { goNext, goPrev, isFirstStep } = useWizard(); + const { + enterpriseConnection, + enterpriseConnectionMutations: { updateConnection }, + } = useConfigureSSO(); + const oauthConfig = enterpriseConnection?.oauthConfig; + const clientIdField = useFormControl('clientId', oauthConfig?.clientId ?? '', { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.credentialsStep.clientId.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.credentialsStep.clientId.placeholder'), + isRequired: true, + }); + const clientSecretField = useFormControl('clientSecret', '', { + type: 'password', + label: localizationKeys('configureSSO.configureStep.oidcCustom.credentialsStep.clientSecret.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.credentialsStep.clientSecret.placeholder'), + isRequired: true, + }); + const [isSubmitting, setIsSubmitting] = React.useState(false); + + const canSubmit = clientIdField.value.trim().length > 0 && clientSecretField.value.trim().length > 0 && !isSubmitting; + + const handleContinue = async (): Promise => { + if (!enterpriseConnection || !canSubmit) { + return; + } + + card.setError(undefined); + setIsSubmitting(true); + + try { + await updateConnection(enterpriseConnection.id, { + oidc: { + clientId: clientIdField.value.trim(), + clientSecret: clientSecretField.value.trim(), + ...(mode === 'discoveryUrl' && oauthConfig?.discoveryUrl !== undefined + ? { discoveryUrl: oauthConfig.discoveryUrl } + : {}), + ...(mode === 'manual' && oauthConfig?.authUrl !== undefined ? { authUrl: oauthConfig.authUrl } : {}), + ...(mode === 'manual' && oauthConfig?.tokenUrl !== undefined ? { tokenUrl: oauthConfig.tokenUrl } : {}), + ...(mode === 'manual' && oauthConfig?.userInfoUrl !== undefined + ? { userInfoUrl: oauthConfig.userInfoUrl } + : {}), + }, + }); + void goNext(); + } catch (err) { + handleError(err as Error, [clientIdField, clientSecretField], card.setError); + setIsSubmitting(false); + } + }; + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + goPrev()} + isDisabled={isFirstStep || isSubmitting} + /> + + + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsConfigurationForm.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsConfigurationForm.tsx new file mode 100644 index 00000000000..bb8b0fe11ea --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsConfigurationForm.tsx @@ -0,0 +1,55 @@ +import type { FieldId } from '@clerk/shared/types'; +import { type JSX } from 'react'; + +import { type LocalizationKey, Text } from '@/customizables'; +import { Form } from '@/elements/Form'; +import type { FormControlState } from '@/ui/utils/useFormControl'; + +type FormControl = FormControlState; + +type DiscoveryUrlForm = { + discoveryUrlField: FormControl; +}; + +type EndpointLabels = { + description: LocalizationKey; +}; + +type ManualEndpointsForm = { + authUrlField: FormControl; + tokenUrlField: FormControl; + userInfoUrlField: FormControl; +}; + +export type OidcEndpointsConfigurationFormProps = + | { mode: 'discoveryUrl'; form: DiscoveryUrlForm; labels: EndpointLabels } + | { mode: 'manual'; form: ManualEndpointsForm; labels: EndpointLabels }; + +export const OidcEndpointsConfigurationForm = (props: OidcEndpointsConfigurationFormProps): JSX.Element => { + return ( + <> + + {props.mode === 'discoveryUrl' ? ( + + + + ) : ( + <> + + + + + + + + + + + )} + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsStep.tsx new file mode 100644 index 00000000000..20c29103f3a --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcEndpointsStep.tsx @@ -0,0 +1,168 @@ +import React, { type JSX } from 'react'; + +import { localizationKeys } from '@/customizables'; +import { useCardState } from '@/elements/contexts'; +import { useFormControl } from '@/ui/utils/useFormControl'; +import { handleError } from '@/utils/errorHandler'; + +import { useConfigureSSO } from '../../../../ConfigureSSOContext'; +import { Step } from '../../../../elements/Step'; +import { useWizard } from '../../../../elements/Wizard'; +import { InnerStepCounter } from '../../../../elements/Wizard/InnerStepCounter'; +import { ActiveConnectionAlert } from '../../shared/ActiveConnectionAlert'; +import { + IdentityProviderConfigurationModes, + type OidcIdpConfigurationMode, +} from '../../shared/IdentityProviderConfigurationModes'; +import { + OidcEndpointsConfigurationForm, + type OidcEndpointsConfigurationFormProps, +} from './OidcEndpointsConfigurationForm'; + +const OIDC_ENDPOINT_MODES = ['discoveryUrl', 'manual'] as const satisfies readonly OidcIdpConfigurationMode[]; + +interface OidcEndpointsStepProps { + mode: OidcIdpConfigurationMode; + onModeChange: (mode: OidcIdpConfigurationMode) => void; +} + +export const OidcEndpointsStep = ({ mode, onModeChange }: OidcEndpointsStepProps): JSX.Element => { + const card = useCardState(); + const { goNext, goPrev, isFirstStep } = useWizard(); + const { + enterpriseConnection, + enterpriseConnectionMutations: { updateConnection }, + } = useConfigureSSO(); + const oauthConfig = enterpriseConnection?.oauthConfig; + const [isSubmitting, setIsSubmitting] = React.useState(false); + + const discoveryUrlField = useFormControl('discoveryUrl', oauthConfig?.discoveryUrl ?? '', { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.discoveryUrl.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.discoveryUrl.placeholder'), + isRequired: true, + }); + const authUrlField = useFormControl('authUrl', oauthConfig?.authUrl ?? '', { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.authUrl.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.authUrl.placeholder'), + isRequired: true, + }); + const tokenUrlField = useFormControl('tokenUrl', oauthConfig?.tokenUrl ?? '', { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.tokenUrl.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.tokenUrl.placeholder'), + isRequired: true, + }); + const userInfoUrlField = useFormControl('userInfoUrl', oauthConfig?.userInfoUrl ?? '', { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.userInfoUrl.label'), + placeholder: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.userInfoUrl.placeholder'), + }); + + const isValid = + mode === 'discoveryUrl' + ? discoveryUrlField.value.trim().length > 0 + : authUrlField.value.trim().length > 0 && tokenUrlField.value.trim().length > 0; + + const canSubmit = isValid && !isSubmitting; + + const formProps: OidcEndpointsConfigurationFormProps = + mode === 'discoveryUrl' + ? { + mode: 'discoveryUrl', + form: { discoveryUrlField }, + labels: { + description: localizationKeys( + 'configureSSO.configureStep.oidcCustom.endpointsStep.discoveryUrl.description', + ), + }, + } + : { + mode: 'manual', + form: { authUrlField, tokenUrlField, userInfoUrlField }, + labels: { + description: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.manual.description'), + }, + }; + + const handleContinue = async (): Promise => { + if (!enterpriseConnection || !canSubmit) { + return; + } + + card.setError(undefined); + setIsSubmitting(true); + + try { + await updateConnection( + enterpriseConnection.id, + mode === 'discoveryUrl' + ? { oidc: { discoveryUrl: discoveryUrlField.value.trim() } } + : { + oidc: { + authUrl: authUrlField.value.trim(), + tokenUrl: tokenUrlField.value.trim(), + userInfoUrl: userInfoUrlField.value.trim(), + }, + }, + ); + void goNext(); + } catch (err) { + handleError( + err as Error, + mode === 'discoveryUrl' ? [discoveryUrlField] : [authUrlField, tokenUrlField, userInfoUrlField], + card.setError, + ); + setIsSubmitting(false); + } + }; + + return ( + <> + + + + + + + { + card.setError(undefined); + onModeChange(nextMode); + }} + labels={{ + ariaLabel: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.modes.ariaLabel'), + discoveryUrl: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.modes.discoveryUrl'), + manual: localizationKeys('configureSSO.configureStep.oidcCustom.endpointsStep.modes.manual'), + }} + /> + + + + + + + + + goPrev()} + isDisabled={isFirstStep || isSubmitting} + /> + + + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcRedirectUriStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcRedirectUriStep.tsx new file mode 100644 index 00000000000..26230ed8131 --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/oidc/shared/OidcRedirectUriStep.tsx @@ -0,0 +1,177 @@ +import { type JSX } from 'react'; + +import { + Badge, + Col, + descriptors, + Flex, + localizationKeys, + Table, + Tbody, + Td, + Text, + Th, + Thead, + Tr, +} from '@/customizables'; +import { ClipboardInput } from '@/elements/ClipboardInput'; +import { Form } from '@/elements/Form'; +import { Checkmark, Clipboard } from '@/icons'; +import { useFormControl } from '@/ui/utils/useFormControl'; + +import { useConfigureSSO } from '../../../../ConfigureSSOContext'; +import { Step } from '../../../../elements/Step'; +import { useWizard } from '../../../../elements/Wizard'; +import { InnerStepCounter } from '../../../../elements/Wizard/InnerStepCounter'; + +type OidcClaimRow = { + id: 'subject' | 'email' | 'firstName' | 'lastName'; + claim: 'sub' | 'email' | 'given_name' | 'family_name'; + isRequired: boolean; +}; + +const OIDC_CLAIM_ROWS: ReadonlyArray = [ + { id: 'subject', claim: 'sub', isRequired: true }, + { id: 'email', claim: 'email', isRequired: true }, + { id: 'firstName', claim: 'given_name', isRequired: false }, + { id: 'lastName', claim: 'family_name', isRequired: false }, +]; + +const OidcClaimsTable = (): JSX.Element => ( + ({ + 'tr > th:first-of-type': { paddingInlineStart: theme.space.$4 }, + })} + > + + + + + + + + {OIDC_CLAIM_ROWS.map(row => ( + + + + + ))} + +
+ ({ fontSize: theme.fontSizes.$xs })} + localizationKey={localizationKeys( + 'configureSSO.configureStep.oidcCustom.redirectUriStep.claims.table.columns.claim', + )} + /> + + ({ fontSize: theme.fontSizes.$xs })} + localizationKey={localizationKeys( + 'configureSSO.configureStep.oidcCustom.redirectUriStep.claims.table.columns.attribute', + )} + /> +
+ ({ gap: theme.space.$2 })} + > + + {row.claim} + + + + + +
+); + +export const OidcRedirectUriStep = (): JSX.Element => { + const { goNext, goPrev, isFirstStep, isLastStep } = useWizard(); + const { enterpriseConnection } = useConfigureSSO(); + const redirectUri = enterpriseConnection?.oauthConfig?.redirectUri ?? ''; + const redirectUriField = useFormControl('redirectUri', redirectUri, { + type: 'text', + label: localizationKeys('configureSSO.configureStep.oidcCustom.redirectUriStep.redirectUri.label'), + isRequired: false, + }); + + return ( + <> + + + + + + ({ gap: theme.space.$5 })}> + ({ gap: theme.space.$1x5 })}> + + + + + + + + + + ({ gap: theme.space.$3 })}> + + + + + + + + + goPrev()} + isDisabled={isFirstStep} + /> + goNext()} + isDisabled={isLastStep} + /> + + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx index 315ef2b0718..ded9cbeafa4 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlCustomConfigureSteps.tsx @@ -24,16 +24,16 @@ import { useConfigureSSO } from '../../../ConfigureSSOContext'; import { Step } from '../../../elements/Step'; import { useWizard, Wizard, type WizardStepConfig } from '../../../elements/Wizard'; import { InnerStepCounter } from '../../../elements/Wizard/InnerStepCounter'; +import { + IdentityProviderConfigurationModes, + type SamlIdpConfigurationMode, +} from '../shared/IdentityProviderConfigurationModes'; import { applySamlSubmitError, buildSamlConfigurationPayload, IdentityProviderConfigurationForm, type IdentityProviderConfigurationFormProps, } from './shared/IdentityProviderConfigurationForm'; -import { - IdentityProviderConfigurationModes, - type IdpConfigurationMode, -} from './shared/IdentityProviderConfigurationModes'; const CUSTOM_STEPS: WizardStepConfig[] = [ { id: 'create-app' }, @@ -308,7 +308,7 @@ const SamlCustomAssignUsersStep = (): JSX.Element => { ); }; -const CUSTOM_SAML_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly IdpConfigurationMode[]; +const CUSTOM_SAML_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly SamlIdpConfigurationMode[]; const SamlCustomIdentityProviderMetadataStep = (): JSX.Element => { const card = useCardState(); @@ -327,7 +327,7 @@ const SamlCustomIdentityProviderMetadataStep = (): JSX.Element => { ); const existingCertPresent = Boolean(samlConnection?.idpCertificate); - const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); + const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); const [certFile, setCertFile] = React.useState(null); // Step-LOCAL submit state for the Continue button. `goNext` bubbles to the // parent (this is the terminal nested step) and the parent DEFERS the diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx index 1431d6f3325..dff36e9feaf 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlGoogleConfigureSteps.tsx @@ -12,16 +12,16 @@ import { useConfigureSSO } from '../../../ConfigureSSOContext'; import { Step } from '../../../elements/Step'; import { useWizard, Wizard, type WizardStepConfig } from '../../../elements/Wizard'; import { InnerStepCounter } from '../../../elements/Wizard/InnerStepCounter'; +import { + IdentityProviderConfigurationModes, + type SamlIdpConfigurationMode, +} from '../shared/IdentityProviderConfigurationModes'; import { applySamlSubmitError, buildSamlConfigurationPayload, IdentityProviderConfigurationForm, type IdentityProviderConfigurationFormProps, } from './shared/IdentityProviderConfigurationForm'; -import { - IdentityProviderConfigurationModes, - type IdpConfigurationMode, -} from './shared/IdentityProviderConfigurationModes'; const GOOGLE_STEPS: WizardStepConfig[] = [ { id: 'create-app' }, @@ -143,7 +143,7 @@ const SamlGoogleCreateAppStep = (): JSX.Element => { ); }; -const GOOGLE_IDP_MODES = ['metadataFile', 'manual'] as const satisfies readonly IdpConfigurationMode[]; +const GOOGLE_IDP_MODES = ['metadataFile', 'manual'] as const satisfies readonly SamlIdpConfigurationMode[]; const SamlGoogleIdentityProviderMetadataStep = (): JSX.Element => { const card = useCardState(); @@ -160,7 +160,7 @@ const SamlGoogleIdentityProviderMetadataStep = (): JSX.Element => { const existingCertPresent = Boolean(samlConnection?.idpCertificate); const existingMetadataPresent = Boolean(samlConnection?.idpMetadata); - const [mode, setMode] = React.useState(hasExistingManualConfig ? 'manual' : 'metadataFile'); + const [mode, setMode] = React.useState(hasExistingManualConfig ? 'manual' : 'metadataFile'); const [metadataFile, setMetadataFile] = React.useState(null); const [certFile, setCertFile] = React.useState(null); // Step-LOCAL submit state for the Continue button. `goNext` bubbles to the diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx index b9b27e58ce1..c7c937028dd 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlMicrosoftConfigureSteps.tsx @@ -33,16 +33,16 @@ import { useConfigureSSO } from '../../../ConfigureSSOContext'; import { Step } from '../../../elements/Step'; import { useWizard, Wizard, type WizardStepConfig } from '../../../elements/Wizard'; import { InnerStepCounter } from '../../../elements/Wizard/InnerStepCounter'; +import { + IdentityProviderConfigurationModes, + type SamlIdpConfigurationMode, +} from '../shared/IdentityProviderConfigurationModes'; import { applySamlSubmitError, buildSamlConfigurationPayload, IdentityProviderConfigurationForm, type IdentityProviderConfigurationFormProps, } from './shared/IdentityProviderConfigurationForm'; -import { - IdentityProviderConfigurationModes, - type IdpConfigurationMode, -} from './shared/IdentityProviderConfigurationModes'; const MICROSOFT_STEPS: WizardStepConfig[] = [ { id: 'create-app' }, @@ -636,7 +636,7 @@ const SamlMicrosoftAttributeMappingStep = (): JSX.Element => { ); }; -const MICROSOFT_SAML_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly IdpConfigurationMode[]; +const MICROSOFT_SAML_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly SamlIdpConfigurationMode[]; const SamlMicrosoftIdentityProviderMetadataStep = (): JSX.Element => { const card = useCardState(); @@ -655,7 +655,7 @@ const SamlMicrosoftIdentityProviderMetadataStep = (): JSX.Element => { ); const existingCertPresent = Boolean(samlConnection?.idpCertificate); - const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); + const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); const [certFile, setCertFile] = React.useState(null); const [isSubmitting, setIsSubmitting] = React.useState(false); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx index 812c357e1b1..ac4e0739ee4 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/SamlOktaConfigureSteps.tsx @@ -25,16 +25,16 @@ import { useConfigureSSO } from '../../../ConfigureSSOContext'; import { Step } from '../../../elements/Step'; import { useWizard, Wizard, type WizardStepConfig } from '../../../elements/Wizard'; import { InnerStepCounter } from '../../../elements/Wizard/InnerStepCounter'; +import { + IdentityProviderConfigurationModes, + type SamlIdpConfigurationMode, +} from '../shared/IdentityProviderConfigurationModes'; import { applySamlSubmitError, buildSamlConfigurationPayload, IdentityProviderConfigurationForm, type IdentityProviderConfigurationFormProps, } from './shared/IdentityProviderConfigurationForm'; -import { - IdentityProviderConfigurationModes, - type IdpConfigurationMode, -} from './shared/IdentityProviderConfigurationModes'; const OKTA_STEPS: WizardStepConfig[] = [ { id: 'create-app' }, @@ -494,7 +494,7 @@ const SamlOktaAssignUsersStep = (): JSX.Element => { ); }; -const OKTA_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly IdpConfigurationMode[]; +const OKTA_IDP_MODES = ['metadataUrl', 'manual'] as const satisfies readonly SamlIdpConfigurationMode[]; const SamlOktaIdentityProviderMetadataStep = (): JSX.Element => { const card = useCardState(); @@ -513,7 +513,7 @@ const SamlOktaIdentityProviderMetadataStep = (): JSX.Element => { ); const existingCertPresent = Boolean(samlConnection?.idpCertificate); - const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); + const [mode, setMode] = React.useState(hasExistingConfig ? 'manual' : 'metadataUrl'); const [certFile, setCertFile] = React.useState(null); // Step-LOCAL submit state for the Continue button. `goNext` bubbles to the // parent (this is the terminal nested step) and the parent DEFERS the diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsx index ed8ac096250..14fad7e2586 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationForm.tsx @@ -21,8 +21,8 @@ import { ArrowUpTray, Close } from '@/icons'; import type { FormControlState } from '@/ui/utils/useFormControl'; import { handleError } from '@/utils/errorHandler'; -import { ActiveConnectionAlert } from './ActiveConnectionAlert'; -import type { IdpConfigurationMode } from './IdentityProviderConfigurationModes'; +import { ActiveConnectionAlert } from '../../shared/ActiveConnectionAlert'; +import type { SamlIdpConfigurationMode } from '../../shared/IdentityProviderConfigurationModes'; type CardState = ReturnType; type FormControl = FormControlState; @@ -180,7 +180,7 @@ const ManualPanel = ({ form, labels }: ManualPanelProps): JSX.Element => ( ); type BuildSamlPayloadParams = { - mode: IdpConfigurationMode; + mode: SamlIdpConfigurationMode; metadataUrl?: { value: string }; metadataFile?: { file: File | null }; manual?: { diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationModes.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationModes.tsx deleted file mode 100644 index 1b75ea36aee..00000000000 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/IdentityProviderConfigurationModes.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { type JSX } from 'react'; - -import { type LocalizationKey, useLocalizations } from '@/customizables'; -import { SegmentedControl } from '@/elements/SegmentedControl'; - -/** - * The possible modes for the identity provider configuration - * - * metadataUrl: Fetch IdP configuration via metadata URL - * metadataFile: Upload IdP configuration via metadata file - * manual: Configure manually each field, such as sign on URL, issuer, and signing certificate - */ -export type IdpConfigurationMode = 'metadataUrl' | 'metadataFile' | 'manual'; - -type ModeLocalizationKeys = Partial>; - -type IdentityProviderConfigurationModesProps = { - modes: readonly IdpConfigurationMode[]; - value: IdpConfigurationMode; - onChange: (mode: IdpConfigurationMode) => void; - labels: { - ariaLabel: LocalizationKey; - } & ModeLocalizationKeys; -}; - -export const IdentityProviderConfigurationModes = ({ - modes, - value, - onChange, - labels, -}: IdentityProviderConfigurationModesProps): JSX.Element => { - const { t } = useLocalizations(); - - return ( - onChange(next as IdpConfigurationMode)} - fullWidth - size='lg' - > - {modes.map(mode => { - const label = labels[mode]; - if (!label) { - return null; - } - - return ( - - ); - })} - - ); -}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/ActiveConnectionAlert.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/ActiveConnectionAlert.tsx similarity index 91% rename from packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/ActiveConnectionAlert.tsx rename to packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/ActiveConnectionAlert.tsx index 36fd518e72b..281cc069a5b 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/saml/shared/ActiveConnectionAlert.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/ActiveConnectionAlert.tsx @@ -3,7 +3,7 @@ import React, { type JSX } from 'react'; import { localizationKeys } from '@/customizables'; import { Alert } from '@/elements/Alert'; -import { useConfigureSSO } from '../../../../ConfigureSSOContext'; +import { useConfigureSSO } from '../../../ConfigureSSOContext'; export const ActiveConnectionAlert = (): JSX.Element | null => { const { enterpriseConnection } = useConfigureSSO(); diff --git a/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/IdentityProviderConfigurationModes.tsx b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/IdentityProviderConfigurationModes.tsx new file mode 100644 index 00000000000..f472cb0bf7d --- /dev/null +++ b/packages/ui/src/components/ConfigureSSO/steps/ConfigureStep/shared/IdentityProviderConfigurationModes.tsx @@ -0,0 +1,50 @@ +import { type JSX } from 'react'; + +import { type LocalizationKey, useLocalizations } from '@/customizables'; +import { SegmentedControl } from '@/elements/SegmentedControl'; + +export type SamlIdpConfigurationMode = 'metadataUrl' | 'metadataFile' | 'manual'; +export type OidcIdpConfigurationMode = 'discoveryUrl' | 'manual'; + +type IdentityProviderConfigurationModesProps = { + modes: readonly Mode[]; + value: Mode; + onChange: (mode: Mode) => void; + labels: { + ariaLabel: LocalizationKey; + } & Partial>; +}; + +export const IdentityProviderConfigurationModes = ({ + modes, + value, + onChange, + labels, +}: IdentityProviderConfigurationModesProps): JSX.Element => { + const { t } = useLocalizations(); + + return ( + onChange(next as Mode)} + fullWidth + size='lg' + > + {modes.map(mode => { + const label = labels[mode]; + if (!label) { + return null; + } + + return ( + + ); + })} + + ); +}; diff --git a/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx b/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx index 7ba827671b5..7fde28ee673 100644 --- a/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx +++ b/packages/ui/src/components/ConfigureSSO/steps/SelectProviderStep.tsx @@ -21,13 +21,14 @@ import { handleError } from '@/utils/errorHandler'; import { ChangeProviderDialog } from '../ChangeProviderDialog'; import { useConfigureSSO } from '../ConfigureSSOContext'; +import { isOidcProvider } from '../domain/organizationEnterpriseConnection'; import { Step } from '../elements/Step'; import { useWizard } from '../elements/Wizard'; -import type { ProviderType } from '../types'; +import type { EnterpriseConnectionProviderType, ProviderType } from '../types'; const MONOCHROMATIC_PROVIDER_ICONS: ReadonlySet = new Set(['okta']); const PROVIDER_GROUPS: ReadonlyArray<{ - id: 'saml'; + id: 'saml' | 'oidc'; label: LocalizationKey; options: ReadonlyArray<{ id: ProviderType; label: LocalizationKey; iconId: string }>; }> = [ @@ -53,21 +54,43 @@ const PROVIDER_GROUPS: ReadonlyArray<{ }, ], }, + { + id: 'oidc', + label: localizationKeys('configureSSO.selectProviderStep.oidc.groupLabel'), + options: [ + { + id: 'oidc_custom', + label: localizationKeys('configureSSO.selectProviderStep.oidc.oidcProvider'), + iconId: 'oidc', + }, + ], + }, ]; const providerLabel = (provider: ProviderType): LocalizationKey | undefined => PROVIDER_GROUPS.flatMap(group => group.options).find(option => option.id === provider)?.label; +const toProviderCard = (provider: EnterpriseConnectionProviderType): ProviderType => + isOidcProvider(provider) ? 'oidc_custom' : provider; + export const SelectProviderStep = (): JSX.Element => { const { organizationEnterpriseConnection: c, enterpriseConnectionMutations: { createConnection, changeProvider }, contentRef, + isOIDCFlowEnabled, } = useConfigureSSO(); const { goNext, goPrev, isFirstStep } = useWizard(); const { t } = useLocalizations(); - const [selected, setSelected] = React.useState(c.provider ?? null); + const providerGroups = React.useMemo( + () => PROVIDER_GROUPS.filter(group => group.id !== 'oidc' || isOIDCFlowEnabled), + [isOIDCFlowEnabled], + ); + + const currentCard = c.provider ? toProviderCard(c.provider) : null; + + const [selected, setSelected] = React.useState(currentCard); const card = useCardState(); const [isSubmitting, setIsSubmitting] = React.useState(false); @@ -78,20 +101,20 @@ export const SelectProviderStep = (): JSX.Element => { setSelected(next); }; - const isChangingProvider = c.hasConnection && selected !== null && selected !== c.provider; + const isChangingProvider = c.hasConnection && selected !== null && selected !== currentCard; const handleContinue = async (): Promise => { if (!selected) { return; } - if (c.hasConnection && selected === c.provider) { + if (c.hasConnection && selected === currentCard) { void goNext(); return; } if (isChangingProvider) { - setChangeFromProvider(c.provider ?? null); + setChangeFromProvider(currentCard); setIsChangeDialogOpen(true); return; } @@ -143,7 +166,7 @@ export const SelectProviderStep = (): JSX.Element => { ({ gap: theme.space.$5 })}> - {PROVIDER_GROUPS.map(group => ( + {providerGroups.map(group => ( ({ provider: undefined as 'saml_okta' | 'saml_custom' | 'saml_google' | undefined, hasConnection: false, + isOIDCFlowEnabled: false, })); vi.mock('../../ConfigureSSOContext', () => ({ @@ -39,6 +40,7 @@ vi.mock('../../ConfigureSSOContext', () => ({ provider: contextState.provider, hasConnection: contextState.hasConnection, }, + isOIDCFlowEnabled: contextState.isOIDCFlowEnabled, }), })); @@ -62,6 +64,7 @@ const resetMocks = () => { changeProvider.mockResolvedValue(undefined); contextState.provider = undefined; contextState.hasConnection = false; + contextState.isOIDCFlowEnabled = false; }; describe('SelectProviderStep', () => { @@ -105,6 +108,26 @@ describe('SelectProviderStep', () => { expect(collectedStyles).toMatch(/img\.clerk\.com\/static\/google\.svg/); }); + describe('OIDC provider (experimental flag)', () => { + it('hides the OIDC provider tile when the flag is off', async () => { + resetMocks(); + const { wrapper } = await createFixtures(); + const { container } = renderStep(wrapper); + + expect(screen.getByRole('radio', { name: 'Okta Workforce' })).toBeInTheDocument(); + expect(container.querySelector('input[value="oidc_custom"]')).not.toBeInTheDocument(); + }); + + it('shows the OIDC provider tile when the flag is on', async () => { + resetMocks(); + contextState.isOIDCFlowEnabled = true; + const { wrapper } = await createFixtures(); + const { container } = renderStep(wrapper); + + expect(container.querySelector('input[value="oidc_custom"]')).toBeInTheDocument(); + }); + }); + it('disables Continue when no provider is selected', async () => { resetMocks(); const { wrapper } = await createFixtures(); diff --git a/packages/ui/src/components/ConfigureSSO/types.ts b/packages/ui/src/components/ConfigureSSO/types.ts index 190fa6cd26e..57056616d18 100644 --- a/packages/ui/src/components/ConfigureSSO/types.ts +++ b/packages/ui/src/components/ConfigureSSO/types.ts @@ -1,4 +1,10 @@ -export type ProviderType = 'saml_okta' | 'saml_custom' | 'saml_google' | 'saml_microsoft'; +export type SamlProviderType = 'saml_okta' | 'saml_custom' | 'saml_google' | 'saml_microsoft'; + +export type OidcProviderType = `oidc_${string}` | `oauth_custom_${string}`; + +export type ProviderType = SamlProviderType | 'oidc_custom'; + +export type EnterpriseConnectionProviderType = SamlProviderType | OidcProviderType; export type WizardStepId = | 'verify-domain'