import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import FileSaver from "file-saver"; import { ActionGroup, AlertVariant, Button, Card, CardBody, CardHeader, CardTitle, FormGroup, PageSection, Switch, Text, TextContent, TextInput, } from "@patternfly/react-core"; import type CertificateRepresentation from "@keycloak/keycloak-admin-client/lib/defs/certificateRepresentation"; import type KeyStoreConfig from "@keycloak/keycloak-admin-client/lib/defs/keystoreConfig"; import { HelpItem } from "../../components/help-enabler/HelpItem"; import { FormAccess } from "../../components/form-access/FormAccess"; import { Controller, useFormContext, useWatch } from "react-hook-form"; import type { ClientForm } from "../ClientDetails"; import { GenerateKeyDialog } from "./GenerateKeyDialog"; import { useFetch, useAdminClient } from "../../context/auth/AdminClient"; import { useAlerts } from "../../components/alert/Alerts"; import { ImportKeyDialog, ImportFile } from "./ImportKeyDialog"; import { Certificate } from "./Certificate"; type KeysProps = { save: () => void; clientId: string; }; const attr = "jwt.credential"; export const Keys = ({ clientId, save }: KeysProps) => { const { t } = useTranslation("clients"); const { control, register, formState: { isDirty }, } = useFormContext(); const adminClient = useAdminClient(); const { addAlert, addError } = useAlerts(); const [keyInfo, setKeyInfo] = useState(); const [openGenerateKeys, setOpenGenerateKeys] = useState(false); const [openImportKeys, setOpenImportKeys] = useState(false); const useJwksUrl = useWatch({ control, name: "attributes.use-jwks-url", defaultValue: "false", }); useFetch( () => adminClient.clients.getKeyInfo({ id: clientId, attr }), (info) => setKeyInfo(info), [] ); const generate = async (config: KeyStoreConfig) => { try { const keyStore = await adminClient.clients.generateAndDownloadKey( { id: clientId, attr, }, config ); FileSaver.saveAs( new Blob([keyStore], { type: "application/octet-stream" }), `keystore.${config.format == "PKCS12" ? "p12" : "jks"}` ); addAlert(t("generateSuccess"), AlertVariant.success); } catch (error) { addError("clients:generateError", error); } }; const importKey = async (importFile: ImportFile) => { try { const formData = new FormData(); const { file, ...rest } = importFile; Object.entries(rest).map((entry) => formData.append(entry[0], entry[1] as string) ); formData.append("file", file.value); await adminClient.clients.uploadCertificate( { id: clientId, attr }, formData ); addAlert(t("importSuccess"), AlertVariant.success); } catch (error) { addError("clients:importError", error); } }; return ( {openGenerateKeys && ( setOpenGenerateKeys(!openGenerateKeys)} save={generate} /> )} {openImportKeys && ( setOpenImportKeys(!openImportKeys)} save={importKey} /> )} {t("jwksUrlConfig")} {t("keysIntro")} } > ( onChange(`${value}`)} /> )} /> {useJwksUrl !== "true" && (keyInfo ? ( ) : ( "No client certificate configured" ))} {useJwksUrl === "true" && ( } > )} ); };