From fad8872b31fc60bc531101d87b95b297f7fb4fcd Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Tue, 28 Nov 2023 17:08:46 +0800 Subject: [PATCH] fix(console,phrases,core): fix SAML attribute mapping (#4978) --- .../console/src/pages/EnterpriseSso/types.ts | 15 ++--- .../Connection/BasicInfo/index.tsx | 21 +++---- .../SamlAttributeMapping/index.module.scss | 3 +- .../Connection/SamlAttributeMapping/index.tsx | 58 ++++++++++--------- .../EnterpriseSsoDetails/Connection/index.tsx | 5 +- packages/core/src/sso/SamlConnector/index.ts | 3 +- .../core/src/sso/SamlConnector/utils.test.ts | 27 +-------- packages/core/src/sso/SamlConnector/utils.ts | 17 +++--- .../core/src/sso/SamlSsoConnector/index.ts | 12 +++- packages/core/src/sso/types/saml.ts | 32 ++++++---- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- .../admin-console/enterprise-sso.ts | 2 +- 25 files changed, 112 insertions(+), 111 deletions(-) diff --git a/packages/console/src/pages/EnterpriseSso/types.ts b/packages/console/src/pages/EnterpriseSso/types.ts index 226336ff2..7dc6315fa 100644 --- a/packages/console/src/pages/EnterpriseSso/types.ts +++ b/packages/console/src/pages/EnterpriseSso/types.ts @@ -5,21 +5,15 @@ */ import { type SsoProviderName, type SsoConnectorWithProviderConfig } from '@logto/schemas'; -export type AttributeMapping = { +type AttributeMapping = { id?: string; email?: string; - phone?: string; name?: string; - avatar?: string; }; -export const attributeKeys = Object.freeze([ - 'id', - 'email', - 'phone', - 'name', - 'avatar', -]) satisfies ReadonlyArray; +export const attributeKeys = Object.freeze(['id', 'email', 'name']) satisfies ReadonlyArray< + keyof AttributeMapping +>; export type SamlGuideFormType = { metadataUrl?: string; @@ -60,6 +54,7 @@ export type ParsedSsoIdentityProviderConfig = } : T extends SsoProviderName.SAML ? { + defaultAttributeMapping: AttributeMapping; serviceProvider: { entityId: string; assertionConsumerServiceUrl: string; diff --git a/packages/console/src/pages/EnterpriseSsoDetails/Connection/BasicInfo/index.tsx b/packages/console/src/pages/EnterpriseSsoDetails/Connection/BasicInfo/index.tsx index fa4bd712f..9d37b184f 100644 --- a/packages/console/src/pages/EnterpriseSsoDetails/Connection/BasicInfo/index.tsx +++ b/packages/console/src/pages/EnterpriseSsoDetails/Connection/BasicInfo/index.tsx @@ -1,5 +1,5 @@ import { SsoProviderName, type SsoConnectorWithProviderConfig } from '@logto/schemas'; -import { conditional } from '@silverhand/essentials'; +import { conditionalString } from '@silverhand/essentials'; import { useContext } from 'react'; import { z } from 'zod'; @@ -51,8 +51,8 @@ function BasicInfo({ ssoConnectorId, providerName, providerConfig }: Props) { const result = providerPropertiesGuard.safeParse(providerConfig); /** - * Used fallback to show the default value anyways but the cases should not happen. - * TODO: @darcyYe refactor to remove the manual guard. + * Should not fallback to some other manually concatenated URL, show empty string instead. + * Empty string should never show up unless the API does not work properly. */ return ( <> @@ -60,10 +60,10 @@ function BasicInfo({ ssoConnectorId, providerName, providerConfig }: Props) { @@ -71,9 +71,10 @@ function BasicInfo({ ssoConnectorId, providerName, providerConfig }: Props) { diff --git a/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.module.scss b/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.module.scss index 957cdf7d7..41bb41577 100644 --- a/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.module.scss +++ b/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.module.scss @@ -23,13 +23,14 @@ .header { width: 100%; - font: var(--font-title-3); > tr { padding-bottom: _.unit(3); } * > th { + font: var(--font-label-2); + color: var(--color-text); text-align: left; } } diff --git a/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.tsx b/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.tsx index c772b070a..ac8735f08 100644 --- a/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.tsx +++ b/packages/console/src/pages/EnterpriseSsoDetails/Connection/SamlAttributeMapping/index.tsx @@ -1,32 +1,39 @@ -import { useMemo } from 'react'; +import { socialUserInfoGuard } from '@logto/connector-kit'; +import { type SsoConnectorWithProviderConfig } from '@logto/schemas'; +import { conditional } from '@silverhand/essentials'; import { useFormContext } from 'react-hook-form'; +import { z } from 'zod'; import CopyToClipboard from '@/ds-components/CopyToClipboard'; import DynamicT from '@/ds-components/DynamicT'; import TextInput from '@/ds-components/TextInput'; -import { - type SamlGuideFormType, - type AttributeMapping, - attributeKeys, -} from '../../../EnterpriseSso/types.js'; +import { attributeKeys, type SamlGuideFormType } from '../../../EnterpriseSso/types.js'; import * as styles from './index.module.scss'; -type Props = { - isReadOnly?: boolean; -}; +type Props = Pick; + +/** + * TODO: Should align this with the guard `samlAttributeMappingGuard` defined in {@link logto/core/src/sso/types/saml.ts}. + * This only applies to SAML-protocol-based SSO connectors. + */ +const providerPropertiesGuard = z.object({ + defaultAttributeMapping: socialUserInfoGuard + .pick({ + id: true, + email: true, + name: true, + }) + .required(), +}); const primaryKey = 'attributeMapping'; -function SamlAttributeMapping({ isReadOnly }: Props) { - const { watch, register } = useFormContext(); - // eslint-disable-next-line react-hooks/exhaustive-deps - const attributeMapping = watch(primaryKey) ?? {}; - const attributeMappingEntries = useMemo>( - () => attributeKeys.map((key) => [key, attributeMapping[key] ?? '']), - [attributeMapping] - ); +function SamlAttributeMapping({ providerConfig }: Props) { + const { register } = useFormContext(); + + const result = providerPropertiesGuard.safeParse(providerConfig); return ( @@ -41,22 +48,19 @@ function SamlAttributeMapping({ isReadOnly }: Props) { - {attributeMappingEntries.map(([key, value]) => { + {attributeKeys.map((key) => { return ( ); diff --git a/packages/console/src/pages/EnterpriseSsoDetails/Connection/index.tsx b/packages/console/src/pages/EnterpriseSsoDetails/Connection/index.tsx index 2c4e900d1..e287646a0 100644 --- a/packages/console/src/pages/EnterpriseSsoDetails/Connection/index.tsx +++ b/packages/console/src/pages/EnterpriseSsoDetails/Connection/index.tsx @@ -132,8 +132,11 @@ function Connection({ isDeleted, data, onUpdated }: P - + )} diff --git a/packages/core/src/sso/SamlConnector/index.ts b/packages/core/src/sso/SamlConnector/index.ts index d1b61ab3b..54ca1c093 100644 --- a/packages/core/src/sso/SamlConnector/index.ts +++ b/packages/core/src/sso/SamlConnector/index.ts @@ -21,10 +21,10 @@ import { parseXmlMetadata, fetchSamlMetadataXml, handleSamlAssertion, - attributeMappingPostProcessor, getExtendedUserInfoFromRawUserProfile, buildSpEntityId, buildAssertionConsumerServiceUrl, + attributeMappingPostProcessor, } from './utils.js'; /** @@ -127,6 +127,7 @@ class SamlConnector { const rawUserProfile = rawProfileParseResult.data; const profileMap = attributeMappingPostProcessor(this.idpConfig.attributeMapping); + return getExtendedUserInfoFromRawUserProfile(rawUserProfile, profileMap); } diff --git a/packages/core/src/sso/SamlConnector/utils.test.ts b/packages/core/src/sso/SamlConnector/utils.test.ts index fcff97089..9a546c63d 100644 --- a/packages/core/src/sso/SamlConnector/utils.test.ts +++ b/packages/core/src/sso/SamlConnector/utils.test.ts @@ -1,11 +1,9 @@ import { attributeMappingPostProcessor, getExtendedUserInfoFromRawUserProfile } from './utils.js'; const expectedDefaultAttributeMapping = { - id: 'id', + id: 'nameID', email: 'email', - phone: 'phone', name: 'name', - avatar: 'avatar', }; describe('attributeMappingPostProcessor', () => { @@ -15,10 +13,9 @@ describe('attributeMappingPostProcessor', () => { }); it('should overwrite specified attributes of `expectedDefaultAttributeMapping`', () => { - expect(attributeMappingPostProcessor({ id: 'sub', avatar: 'picture' })).toEqual({ + expect(attributeMappingPostProcessor({ id: 'sub' })).toEqual({ ...expectedDefaultAttributeMapping, id: 'sub', - avatar: 'picture', }); }); }); @@ -46,24 +43,4 @@ describe('getExtendedUserInfoFromRawUserProfile', () => { avatar: 'pic.png', }); }); - - it('should correctly map with specific fields specified and with extended fields unchanged', () => { - const keyMapping = attributeMappingPostProcessor({ phone: 'cell_phone', avatar: 'picture' }); - const rawUserProfile = { - id: 'foo', - sub: 'bar', - email: 'test@logto.io', - cell_phone: '123456789', - picture: 'pic.png', - extend_field: 'extend_field', - }; - expect(getExtendedUserInfoFromRawUserProfile(rawUserProfile, keyMapping)).toEqual({ - id: 'foo', - sub: 'bar', - email: 'test@logto.io', - phone: '123456789', - avatar: 'pic.png', - extend_field: 'extend_field', - }); - }); }); diff --git a/packages/core/src/sso/SamlConnector/utils.ts b/packages/core/src/sso/SamlConnector/utils.ts index a7dc49011..432f7eebf 100644 --- a/packages/core/src/sso/SamlConnector/utils.ts +++ b/packages/core/src/sso/SamlConnector/utils.ts @@ -1,5 +1,6 @@ import * as validator from '@authenio/samlify-node-xmllint'; -import { type Optional, conditional, appendPath } from '@silverhand/essentials'; +import { type Optional, appendPath } from '@silverhand/essentials'; +import { conditional } from '@silverhand/essentials'; import { HTTPError, got } from 'got'; import * as saml from 'samlify'; import { z } from 'zod'; @@ -13,11 +14,11 @@ import { } from '../types/error.js'; import { defaultAttributeMapping, - type CustomizableAttributeMap, - type AttributeMap, extendedSocialUserInfoGuard, + type AttributeMap, type ExtendedSocialUserInfo, type SamlIdentityProviderMetadata, + type CustomizableAttributeMap, samlIdentityProviderMetadataGuard, } from '../types/saml.js'; @@ -107,15 +108,16 @@ export const fetchSamlMetadataXml = async (metadataUrl: string): Promise, - keyMapping: AttributeMap + attributeMapping: AttributeMap ): ExtendedSocialUserInfo => { const keyMap = new Map( - Object.entries(keyMapping).map(([destination, source]) => [source, destination]) + Object.entries(attributeMapping).map(([destination, source]) => [source, destination]) ); const mappedUserProfile = Object.fromEntries( @@ -169,7 +171,8 @@ export const handleSamlAssertion = async ( // eslint-disable-next-line @typescript-eslint/no-unsafe-return return { ...(Boolean(assertionResult.extract.nameID) && { - id: assertionResult.extract.nameID, + // Usually identity provider DOES NOT allow the configuration of `nameID` claim name. + nameID: assertionResult.extract.nameID, }), ...assertionResult.extract.attributes, }; diff --git a/packages/core/src/sso/SamlSsoConnector/index.ts b/packages/core/src/sso/SamlSsoConnector/index.ts index 2f2294774..1fd93318d 100644 --- a/packages/core/src/sso/SamlSsoConnector/index.ts +++ b/packages/core/src/sso/SamlSsoConnector/index.ts @@ -7,7 +7,11 @@ import assertThat from '#src/utils/assert-that.js'; import SamlConnector from '../SamlConnector/index.js'; import { type SingleSignOnFactory } from '../index.js'; import { type SingleSignOn, type SingleSignOnConnectorData } from '../types/index.js'; -import { samlConnectorConfigGuard, type SamlMetadata } from '../types/saml.js'; +import { + defaultAttributeMapping, + samlConnectorConfigGuard, + type SamlMetadata, +} from '../types/saml.js'; import { type SingleSignOnConnectorSession, type CreateSingleSignOnSession, @@ -43,14 +47,16 @@ export class SamlSsoConnector extends SamlConnector implements SingleSignOn { } /** - * ServiceProvider: SP metadata - * identityProvider: IdP metadata. Returns undefined if the idp config is invalid. + * `defaultAttributeMapping`: Default attribute mapping + * `serviceProvider`: SP metadata + * `identityProvider`: IdP metadata. Returns undefined if the idp config is invalid. */ async getConfig(): Promise { const serviceProvider = this.serviceProviderMetadata; const identityProvider = await trySafe(async () => this.getSamlIdpMetadata()); return { + defaultAttributeMapping, serviceProvider, identityProvider, }; diff --git a/packages/core/src/sso/types/saml.ts b/packages/core/src/sso/types/saml.ts index da6963d40..024ced4b0 100644 --- a/packages/core/src/sso/types/saml.ts +++ b/packages/core/src/sso/types/saml.ts @@ -2,16 +2,25 @@ import { socialUserInfoGuard } from '@logto/connector-kit'; import { z } from 'zod'; // Since the SAML SSO user info will extend the basic social user info (will contain extra info like `organization`, `role` etc.), but for now we haven't decide what should be included in extended user info, so we just use the basic social user info guard here to keep SSOT. -const samlAttributeMappingGuard = socialUserInfoGuard; +const samlAttributeMappingGuard = socialUserInfoGuard + .pick({ + id: true, + email: true, + name: true, + }) + .required(); -// eslint-disable-next-line no-restricted-syntax -export const defaultAttributeMapping = Object.fromEntries( - Object.keys(samlAttributeMappingGuard.shape).map((key) => [key, key]) -) as AttributeMap; +export const defaultAttributeMapping: AttributeMap = { + id: 'nameID', + email: 'email', + name: 'name', +}; -const customizableAttributeMappingGuard = samlAttributeMappingGuard.partial(); -export type CustomizableAttributeMap = z.infer; -export type AttributeMap = Required; +const customizableAttributeMapGuard = samlAttributeMappingGuard.partial(); + +export type CustomizableAttributeMap = z.infer; + +export type AttributeMap = z.infer; /** * This is the metadata of SAML service provider, automatically generated by `tenantId` and `ssoConnectorId`. @@ -38,21 +47,22 @@ export const samlConnectorConfigGuard = z.union([ // Config using Metadata URL z.object({ metadataUrl: z.string(), - attributeMapping: customizableAttributeMappingGuard.optional(), + attributeMapping: customizableAttributeMapGuard.optional(), }), // Config using Metadata XML z.object({ metadata: z.string(), - attributeMapping: customizableAttributeMappingGuard.optional(), + attributeMapping: customizableAttributeMapGuard.optional(), }), // Config using Metadata detail samlIdentityProviderMetadataGuard.extend({ - attributeMapping: customizableAttributeMappingGuard.optional(), + attributeMapping: customizableAttributeMapGuard.optional(), }), ]); export type SamlConnectorConfig = z.infer; const samlMetadataGuard = z.object({ + defaultAttributeMapping: samlAttributeMappingGuard, serviceProvider: samlServiceProviderMetadataGuard, identityProvider: samlIdentityProviderMetadataGuard.optional(), }); diff --git a/packages/phrases/src/locales/de/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/de/translation/admin-console/enterprise-sso.ts index 75d593098..1fa6ed6f7 100644 --- a/packages/phrases/src/locales/de/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/de/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/en/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/en/translation/admin-console/enterprise-sso.ts index fea0b59ba..5e2adaa50 100644 --- a/packages/phrases/src/locales/en/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/en/translation/admin-console/enterprise-sso.ts @@ -37,7 +37,7 @@ const enterprise_sso = { title: 'Attribute mappings', description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', col_idp_claims: 'Claim name of identity provider', idp_claim_tooltip: 'The claim name of the identity provider', }, diff --git a/packages/phrases/src/locales/es/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/es/translation/admin-console/enterprise-sso.ts index 9bbe48a4a..833973364 100644 --- a/packages/phrases/src/locales/es/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/es/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/fr/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/fr/translation/admin-console/enterprise-sso.ts index 2df66073e..a764dac7a 100644 --- a/packages/phrases/src/locales/fr/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/fr/translation/admin-console/enterprise-sso.ts @@ -49,7 +49,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/it/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/it/translation/admin-console/enterprise-sso.ts index 932590275..39b877b0a 100644 --- a/packages/phrases/src/locales/it/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/it/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/ja/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/ja/translation/admin-console/enterprise-sso.ts index 87b3b5098..433d53aaf 100644 --- a/packages/phrases/src/locales/ja/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/ja/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/ko/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/ko/translation/admin-console/enterprise-sso.ts index 2332c847f..36234fb6b 100644 --- a/packages/phrases/src/locales/ko/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/ko/translation/admin-console/enterprise-sso.ts @@ -47,7 +47,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/enterprise-sso.ts index f3b5012b4..dda5f1edb 100644 --- a/packages/phrases/src/locales/pl-pl/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/enterprise-sso.ts index 422ac8fdb..3ccb7f035 100644 --- a/packages/phrases/src/locales/pt-br/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/enterprise-sso.ts index ed103d641..099515d5d 100644 --- a/packages/phrases/src/locales/pt-pt/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/ru/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/ru/translation/admin-console/enterprise-sso.ts index 776e4697b..32de5534a 100644 --- a/packages/phrases/src/locales/ru/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/ru/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/enterprise-sso.ts index c70c255f2..9ab33a114 100644 --- a/packages/phrases/src/locales/tr-tr/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/enterprise-sso.ts @@ -48,7 +48,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/enterprise-sso.ts index ff7c417fd..146923158 100644 --- a/packages/phrases/src/locales/zh-cn/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/enterprise-sso.ts @@ -47,7 +47,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/enterprise-sso.ts index 04a704d46..dda2c72e0 100644 --- a/packages/phrases/src/locales/zh-hk/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/enterprise-sso.ts @@ -47,7 +47,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */ diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/enterprise-sso.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/enterprise-sso.ts index 0729706e4..230ed91b5 100644 --- a/packages/phrases/src/locales/zh-tw/translation/admin-console/enterprise-sso.ts +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/enterprise-sso.ts @@ -47,7 +47,7 @@ const enterprise_sso = { description: '`id` and `email` are required to sync user profile from IdP. Enter the following claim name and value in your IdP.', /** UNTRANSLATED */ - col_sp_claims: 'Claim name of Logto', + col_sp_claims: 'Value of service provider (Logto)', /** UNTRANSLATED */ col_idp_claims: 'Claim name of identity provider', /** UNTRANSLATED */
- {isReadOnly ? ( - - ) : ( - - )} +