Minor UI fixes on 'Keys' tab of SAML client

closes #43304

Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
mposolda 2025-10-13 10:33:12 +02:00 committed by Marek Posolda
parent fa581c8148
commit a77c4a6ad2
4 changed files with 40 additions and 11 deletions

View File

@ -208,7 +208,7 @@ directGrantHelp=Select the flow you want to use for direct grant authentication.
unlockUsersSuccess=Any temporarily locked users are now unlocked
jsonType.tooltip=JSON type that should be used to populate the json claim in the token. long, int, boolean, String and JSON are valid values.
emptyPrimaryAction=Add predefined mapper
enableClientSignatureRequired=Enable "Client signature required"?
enableClientSignatureRequired=Enable "{{key}}"?
supportedApplicationsHelp=Applications that are known to work with the current OTP policy.
enableStartTLS=Enable StartTLS
syncModeOverride=Sync mode override
@ -911,7 +911,7 @@ deleteScopeConfirm=If you delete this authorization scope, some permissions will
updateOtpSuccess=OTP policy successfully updated
title=Authentication
deleteAttributeError=Attribute not deleted: {{error}}
enableClientSignatureRequiredExplain=If you enable "Client signature required", the adapter of this client will be updated. You may need to download a new adapter for this client. You need to generate or import keys for this client otherwise the authentication will not work.
enableClientSignatureRequiredExplain=If you enable "{{key}}", the adapter of this client will be updated. You may need to download a new adapter for this client. You need to generate or import keys for this client otherwise the authentication will not work.
policiesConfigTypes.formView=Form view
residentKey.No=No
nodeReRegistrationTimeout=Node Re-registration timeout
@ -999,6 +999,7 @@ testConnectionError=Error\! {{error}}
authenticatedAccessPoliciesHelp=Those Policies are used when Client Registration Service is invoked by authenticated request. This means that the request contains Initial Access Token or Bearer Token.
deleteClientPolicyProfileSuccess=Profile successfully removed from the policy.
reGenerateSigningExplain=If you regenerate the signing key for client, the Keycloak database will be updated, and you may need to download a new adapter for this client.
reGenerateEncryptionExplain=If you regenerate the encryption key for client, the Keycloak database will be updated, and you may need to download a new adapter for this client.
evaluate=Evaluate
enableLdapv3Password=Enable the LDAPv3 password modify extended operation
status=Status
@ -1416,6 +1417,7 @@ deleteConfirmClientScopes=Are you sure you want to delete this client scope?
forceAuthenticationHelp=Indicates whether the identity provider must authenticate the presenter directly rather than rely on a previous security context.
testClusterAvailability=Test cluster availability
reGenerateSigning=Regenerate signing key for this client
reGenerateEncryption=Regenerate encryption key for this client
authorizationEncryptedResponseAlgHelp=JWA Algorithm used for key management in encrypting the authorization response when the response mode is jwt. This option is needed if you want encrypted authorization response. If left empty, the authorization response is just signed, but not encrypted.
deleteConfirmGroup_other=Are you sure you want to delete these groups?
scopePermissions.users.manage-description=Policies that decide if an administrator can manage all users in the realm
@ -1612,9 +1614,11 @@ UPDATE_PASSWORD=Update password (UPDATE_PASSWORD)
version=Version
synchronizationSettings=Synchronization settings
certificateHelp=Client Certificate for validate JWT issued by client and signed by Client private key from your keystore.
samlclientSignatureCertificateHelp=Client Certificate of public key for validate SAML requests and responses signed by SAML client.
samlencryptAssertionsCertificateHelp=Client Certificate of public key for encrypt SAML assertions.
resetPasswordError=Error resetting password\: {{error}}
associatedPermissions=Associated permission
encryptionKeysConfigExplain=If you enable the "Encryption assertions" below, the SAML assertions will be encrypted with the client's public key. If the client provides a SP Metadata Descriptor URL with signing and encryption keys, you can enable automatic management of keys with the option "Use metadata descriptor URL" in the "Signature and Encryption" section of the "Settings" tab. You can also configure manually the encryption key by generating or importing it on activation. When this option is enabled, the encryption details can be modified in the "Settings" tab, section "Signature and Encryption".
encryptionKeysConfigExplain=If you enable the "Encrypt assertions" below, the SAML assertions will be encrypted with the client's public key. If the client provides a SP Metadata Descriptor URL with signing and encryption keys, you can enable automatic management of keys with the option "Use metadata descriptor URL" in the "Signature and Encryption" section of the "Settings" tab. You can also configure manually the encryption key by generating or importing it on activation. When this option is enabled, the encryption details can be modified in the "Settings" tab, section "Signature and Encryption".
preserveGroupInheritanceHelp=Flag whether group inheritance from LDAP should be propagated to Keycloak. If false, then all LDAP groups will be mapped as flat top-level groups in Keycloak. Otherwise group inheritance is preserved into Keycloak, but the group sync might fail if LDAP structure contains recursions or multiple parent groups per child groups.
createScopeBasedPermission=Create scope-based permission
showMore=Show more

View File

@ -10,6 +10,7 @@ type CertificateProps = Omit<CertificateDisplayProps, "id"> & {
type CertificateDisplayProps = {
id: string;
helpTextKey?: string;
keyInfo?: CertificateRepresentation;
};
@ -27,7 +28,11 @@ const CertificateDisplay = ({ id, keyInfo }: CertificateDisplayProps) => {
);
};
export const Certificate = ({ keyInfo, plain = false }: CertificateProps) => {
export const Certificate = ({
helpTextKey = "certificateHelp",
keyInfo,
plain = false,
}: CertificateProps) => {
const { t } = useTranslation();
const id = useId();
@ -37,7 +42,7 @@ export const Certificate = ({ keyInfo, plain = false }: CertificateProps) => {
<FormGroup
label={t("certificate")}
fieldId={id}
labelIcon={<HelpItem helpText={t("certificateHelp")} fieldLabelId={id} />}
labelIcon={<HelpItem helpText={t(helpTextKey)} fieldLabelId={id} />}
>
<CertificateDisplay id={id} keyInfo={keyInfo} />
</FormGroup>

View File

@ -42,6 +42,7 @@ type KeyMapping = {
name: string;
title: string;
key: string;
regenerateKey: string;
relatedKeys: string[];
};
@ -53,12 +54,14 @@ const KEYS_MAPPING: { [key in KeyTypes]: KeyMapping } = {
name: convertAttributeNameToForm("attributes.saml.client.signature"),
title: "signingKeysConfig",
key: "clientSignature",
regenerateKey: "reGenerateSigning",
relatedKeys: [],
},
"saml.encryption": {
name: convertAttributeNameToForm("attributes.saml.encrypt"),
title: "encryptionKeysConfig",
key: "encryptAssertions",
regenerateKey: "reGenerateEncryption",
relatedKeys: [
convertAttributeNameToForm("attributes.saml.encryption.algorithm"),
convertAttributeNameToForm("attributes.saml.encryption.keyAlgorithm"),
@ -164,7 +167,10 @@ const KeySection = ({
<Card isFlat>
<CardBody className="kc-form-panel__body">
<Form isHorizontal>
<Certificate keyInfo={keyInfo} />
<Certificate
helpTextKey={`saml${key}CertificateHelp`}
keyInfo={keyInfo}
/>
<ActionGroup>
<Button
variant="secondary"
@ -253,9 +259,12 @@ export const SamlKeys = ({ clientId, save }: SamlKeysProps) => {
},
});
const regenerateKey = selectedType
? KEYS_MAPPING[selectedType].regenerateKey
: "";
const [toggleReGenerateDialog, ReGenerateConfirm] = useConfirmDialog({
titleKey: "reGenerateSigning",
messageKey: "reGenerateSigningExplain",
titleKey: regenerateKey,
messageKey: regenerateKey + "Explain",
continueButtonLabel: "yes",
cancelButtonLabel: "no",
onConfirm: async () => {
@ -269,6 +278,7 @@ export const SamlKeys = ({ clientId, save }: SamlKeysProps) => {
<SamlKeysDialog
id={clientId}
attr={isChanged}
localeKey={key}
onClose={() => {
setIsChanged(undefined);
for (const key of KEYS_MAPPING[selectedType!].relatedKeys) {

View File

@ -32,6 +32,7 @@ import type { KeyTypes } from "./SamlKeys";
type SamlKeysDialogProps = {
id: string;
attr: KeyTypes;
localeKey: string;
onClose: () => void;
onCancel: () => void;
};
@ -68,6 +69,7 @@ export const submitForm = async (
export const SamlKeysDialog = ({
id,
attr,
localeKey,
onClose,
onCancel,
}: SamlKeysDialogProps) => {
@ -120,8 +122,16 @@ export const SamlKeysDialog = ({
aria-label={t("enableClientSignatureRequiredModal")}
header={
<TextContent>
<Title headingLevel="h1">{t("enableClientSignatureRequired")}</Title>
<Text>{t("enableClientSignatureRequiredExplain")}</Text>
<Title headingLevel="h1">
{t("enableClientSignatureRequired", {
key: t(localeKey),
})}
</Title>
<Text>
{t("enableClientSignatureRequiredExplain", {
key: t(localeKey),
})}
</Text>
</TextContent>
}
isOpen={true}
@ -187,7 +197,7 @@ export const SamlKeysDialog = ({
fieldId="certificate"
labelIcon={
<HelpItem
helpText={t("certificateHelp")}
helpText={t(`saml${localeKey}CertificateHelp`)}
fieldLabelId="certificate"
/>
}