import { d as defineComponent, at as useRootStore, dQ as useSSOStore, a as useToast, ax as useDocumentTitle, aA as usePageRedirectionHelper, x as computed, c as useI18n, eY as SupportedProtocols, r as ref, o as onMounted, a8 as resolveComponent, h as createElementBlock, g as openBlock, j as createBaseVNode, i as createVNode, f as createCommentVNode, w as withCtx, k as createTextVNode, t as toDisplayString, l as unref, m as N8nHeading, n as normalizeClass, cK as InfoTip, F as Fragment, A as renderList, e as createBlock, e2 as _sfc_main$1, B as withModifiers, e1 as N8nSelect, eZ as CopyInput, O as N8nRadioButtons, cT as N8nInput, a9 as Tooltip, q as N8nButton, dR as N8nActionBox, am as useMessage, an as MODAL_CONFIRM, al as useTelemetry, _ as _export_sfc } from "./index-CeNA_ukL.js"; const _hoisted_1 = { class: "pb-2xl" }; const _hoisted_2 = { href: "https://docs.n8n.io/user-management/saml/", target: "_blank" }; const _hoisted_3 = { key: 1 }; const _hoisted_4 = { key: 0, "data-test-id": "sso-content-licensed" }; const _hoisted_5 = { class: "mt-2xs mb-s" }; const _hoisted_6 = { key: 0 }; const _hoisted_7 = { key: 1 }; const _hoisted_8 = { key: 2 }; const _hoisted_9 = { key: 0 }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "SettingsSso", setup(__props) { const IdentityProviderSettingsType = { URL: "url", XML: "xml" }; const i18n = useI18n(); const telemetry = useTelemetry(); const rootStore = useRootStore(); const ssoStore = useSSOStore(); const message = useMessage(); const toast = useToast(); const documentTitle = useDocumentTitle(); const pageRedirectionHelper = usePageRedirectionHelper(); const ssoActivatedLabel = computed( () => ssoStore.isSamlLoginEnabled ? i18n.baseText("settings.sso.activated") : i18n.baseText("settings.sso.deactivated") ); const oidcActivatedLabel = computed( () => ssoStore.isOidcLoginEnabled ? i18n.baseText("settings.sso.activated") : i18n.baseText("settings.sso.deactivated") ); const options = computed(() => { return [ { label: SupportedProtocols.SAML.toUpperCase(), value: SupportedProtocols.SAML }, { label: ssoStore.isEnterpriseOidcEnabled ? SupportedProtocols.OIDC.toUpperCase() : `${SupportedProtocols.OIDC.toUpperCase()} (${i18n.baseText("generic.upgradeToEnterprise")})`, value: SupportedProtocols.OIDC } ]; }); const ssoSettingsSaved = ref(false); const entityId = ref(); const clientId = ref(""); const clientSecret = ref(""); const discoveryEndpoint = ref(""); const authProtocol = ref(SupportedProtocols.SAML); const ipsOptions = ref([ { label: i18n.baseText("settings.sso.settings.ips.options.url"), value: IdentityProviderSettingsType.URL }, { label: i18n.baseText("settings.sso.settings.ips.options.xml"), value: IdentityProviderSettingsType.XML } ]); const ipsType = ref(IdentityProviderSettingsType.URL); const metadataUrl = ref(); const metadata = ref(); const redirectUrl = ref(); const isSaveEnabled = computed(() => { if (ipsType.value === IdentityProviderSettingsType.URL) { return !!metadataUrl.value && metadataUrl.value !== ssoStore.samlConfig?.metadataUrl; } else if (ipsType.value === IdentityProviderSettingsType.XML) { return !!metadata.value && metadata.value !== ssoStore.samlConfig?.metadata; } return false; }); const isTestEnabled = computed(() => { if (ipsType.value === IdentityProviderSettingsType.URL) { return !!metadataUrl.value && ssoSettingsSaved.value; } else if (ipsType.value === IdentityProviderSettingsType.XML) { return !!metadata.value && ssoSettingsSaved.value; } return false; }); async function loadSamlConfig() { if (!ssoStore.isEnterpriseSamlEnabled) { return; } try { await getSamlConfig(); } catch (error) { toast.showError(error, "error"); } } const getSamlConfig = async () => { const config = await ssoStore.getSamlConfig(); entityId.value = config?.entityID; redirectUrl.value = config?.returnUrl; if (config?.metadataUrl) { ipsType.value = IdentityProviderSettingsType.URL; } else if (config?.metadata) { ipsType.value = IdentityProviderSettingsType.XML; } metadata.value = config?.metadata; metadataUrl.value = config?.metadataUrl; ssoSettingsSaved.value = !!config?.metadata; }; const trackUpdateSettings = () => { const trackingMetadata = { instance_id: rootStore.instanceId, authentication_method: authProtocol.value }; if (authProtocol.value === SupportedProtocols.SAML) { trackingMetadata.identity_provider = ipsType.value === "url" ? "metadata" : "xml"; trackingMetadata.is_active = ssoStore.isSamlLoginEnabled; } else if (authProtocol.value === SupportedProtocols.OIDC) { trackingMetadata.discovery_endpoint = discoveryEndpoint.value; trackingMetadata.is_active = ssoStore.isOidcLoginEnabled; } telemetry.track("User updated single sign on settings", trackingMetadata); }; const onSave = async () => { try { validateInput(); const config = ipsType.value === IdentityProviderSettingsType.URL ? { metadataUrl: metadataUrl.value } : { metadata: metadata.value }; await ssoStore.saveSamlConfig(config); ssoStore.selectedAuthProtocol = authProtocol.value; if (!ssoStore.isSamlLoginEnabled) { const answer = await message.confirm( i18n.baseText("settings.sso.settings.save.activate.message"), i18n.baseText("settings.sso.settings.save.activate.title"), { confirmButtonText: i18n.baseText("settings.sso.settings.save.activate.test"), cancelButtonText: i18n.baseText("settings.sso.settings.save.activate.cancel") } ); if (answer === "confirm") { await onTest(); } } trackUpdateSettings(); } catch (error) { toast.showError(error, i18n.baseText("settings.sso.settings.save.error")); return; } finally { await getSamlConfig(); } }; const onTest = async () => { try { const url = await ssoStore.testSamlConfig(); if (typeof window !== "undefined") { window.open(url, "_blank"); } } catch (error) { toast.showError(error, "error"); } }; const validateInput = () => { if (ipsType.value === IdentityProviderSettingsType.URL) { try { const parsedUrl = new URL(metadataUrl.value); if (parsedUrl.protocol !== "https:" && parsedUrl.protocol !== "http:") { throw new Error("The provided protocol is not supported"); } } catch (error) { throw new Error(i18n.baseText("settings.sso.settings.ips.url.invalid")); } } }; const goToUpgrade = () => { void pageRedirectionHelper.goToUpgrade("sso", "upgrade-sso"); }; const isToggleSsoDisabled = computed(() => { if (ssoStore.isSamlLoginEnabled) { return false; } return !ssoSettingsSaved.value; }); onMounted(async () => { documentTitle.set(i18n.baseText("settings.sso.title")); await Promise.all([loadSamlConfig(), loadOidcConfig()]); ssoStore.initializeSelectedProtocol(); authProtocol.value = ssoStore.selectedAuthProtocol || SupportedProtocols.SAML; }); const getOidcConfig = async () => { const config = await ssoStore.getOidcConfig(); clientId.value = config.clientId; clientSecret.value = config.clientSecret; discoveryEndpoint.value = config.discoveryEndpoint; }; async function loadOidcConfig() { if (!ssoStore.isEnterpriseOidcEnabled) { return; } try { await getOidcConfig(); } catch (error) { toast.showError(error, "error"); } } function onAuthProtocolUpdated(value) { authProtocol.value = value; } const cannotSaveOidcSettings = computed(() => { return ssoStore.oidcConfig?.clientId === clientId.value && ssoStore.oidcConfig?.clientSecret === clientSecret.value && ssoStore.oidcConfig?.discoveryEndpoint === discoveryEndpoint.value && ssoStore.oidcConfig?.loginEnabled === ssoStore.isOidcLoginEnabled; }); async function onOidcSettingsSave() { if (ssoStore.oidcConfig?.loginEnabled && !ssoStore.isOidcLoginEnabled) { const confirmAction = await message.confirm( i18n.baseText("settings.oidc.confirmMessage.beforeSaveForm.message"), i18n.baseText("settings.oidc.confirmMessage.beforeSaveForm.headline"), { cancelButtonText: i18n.baseText( "settings.ldap.confirmMessage.beforeSaveForm.cancelButtonText" ), confirmButtonText: i18n.baseText( "settings.ldap.confirmMessage.beforeSaveForm.confirmButtonText" ) } ); if (confirmAction !== MODAL_CONFIRM) return; } try { const newConfig = await ssoStore.saveOidcConfig({ clientId: clientId.value, clientSecret: clientSecret.value, discoveryEndpoint: discoveryEndpoint.value, loginEnabled: ssoStore.isOidcLoginEnabled }); ssoStore.selectedAuthProtocol = authProtocol.value; clientSecret.value = newConfig.clientSecret; trackUpdateSettings(); } catch (error) { toast.showError(error, i18n.baseText("settings.sso.settings.save.error_oidc")); return; } finally { await getOidcConfig(); } } return (_ctx, _cache) => { const _component_n8n_heading = N8nHeading; const _component_n8n_info_tip = InfoTip; const _component_N8nOption = _sfc_main$1; const _component_N8nSelect = N8nSelect; const _component_n8n_radio_buttons = N8nRadioButtons; const _component_n8n_input = N8nInput; const _component_el_switch = resolveComponent("el-switch"); const _component_n8n_tooltip = Tooltip; const _component_n8n_button = N8nButton; const _component_n8n_action_box = N8nActionBox; const _component_N8nInput = N8nInput; return openBlock(), createElementBlock("div", _hoisted_1, [ createBaseVNode("div", { class: normalizeClass(_ctx.$style.heading) }, [ createVNode(_component_n8n_heading, { size: "2xlarge" }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(i18n).baseText("settings.sso.title")), 1) ]), _: 1 }) ], 2), createVNode(_component_n8n_info_tip, null, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(i18n).baseText("settings.sso.info")) + " ", 1), createBaseVNode("a", _hoisted_2, toDisplayString(unref(i18n).baseText("settings.sso.info.link")), 1) ]), _: 1 }), unref(ssoStore).isEnterpriseSamlEnabled || unref(ssoStore).isEnterpriseOidcEnabled ? (openBlock(), createElementBlock("div", { key: 0, "data-test-id": "sso-auth-protocol-select", class: normalizeClass(_ctx.$style.group) }, [ _cache[9] || (_cache[9] = createBaseVNode("label", null, "Select Authentication Protocol", -1)), createBaseVNode("div", null, [ createVNode(_component_N8nSelect, { filterable: "", "model-value": authProtocol.value, placeholder: unref(i18n).baseText("parameterInput.select"), "onUpdate:modelValue": onAuthProtocolUpdated, onKeydown: _cache[0] || (_cache[0] = withModifiers(() => { }, ["stop"])) }, { default: withCtx(() => [ (openBlock(true), createElementBlock(Fragment, null, renderList(options.value, ({ label, value }) => { return openBlock(), createBlock(_component_N8nOption, { key: value, value, label, "data-test-id": "credential-select-option" }, null, 8, ["value", "label"]); }), 128)) ]), _: 1 }, 8, ["model-value", "placeholder"]) ]) ], 2)) : createCommentVNode("", true), authProtocol.value === unref(SupportedProtocols).SAML ? (openBlock(), createElementBlock("div", _hoisted_3, [ unref(ssoStore).isEnterpriseSamlEnabled ? (openBlock(), createElementBlock("div", _hoisted_4, [ createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ createBaseVNode("label", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.redirectUrl.label")), 1), createVNode(CopyInput, { value: redirectUrl.value, "copy-button-text": unref(i18n).baseText("generic.clickToCopy"), "toast-title": unref(i18n).baseText("settings.sso.settings.redirectUrl.copied") }, null, 8, ["value", "copy-button-text", "toast-title"]), createBaseVNode("small", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.redirectUrl.help")), 1) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ createBaseVNode("label", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.entityId.label")), 1), createVNode(CopyInput, { value: entityId.value, "copy-button-text": unref(i18n).baseText("generic.clickToCopy"), "toast-title": unref(i18n).baseText("settings.sso.settings.entityId.copied") }, null, 8, ["value", "copy-button-text", "toast-title"]), createBaseVNode("small", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.entityId.help")), 1) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ createBaseVNode("label", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.ips.label")), 1), createBaseVNode("div", _hoisted_5, [ createVNode(_component_n8n_radio_buttons, { modelValue: ipsType.value, "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => ipsType.value = $event), options: ipsOptions.value }, null, 8, ["modelValue", "options"]) ]), ipsType.value === IdentityProviderSettingsType.URL ? (openBlock(), createElementBlock("div", _hoisted_6, [ createVNode(_component_n8n_input, { modelValue: metadataUrl.value, "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => metadataUrl.value = $event), type: "text", name: "metadataUrl", size: "large", placeholder: unref(i18n).baseText("settings.sso.settings.ips.url.placeholder"), "data-test-id": "sso-provider-url" }, null, 8, ["modelValue", "placeholder"]), createBaseVNode("small", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.ips.url.help")), 1) ])) : createCommentVNode("", true), ipsType.value === IdentityProviderSettingsType.XML ? (openBlock(), createElementBlock("div", _hoisted_7, [ createVNode(_component_n8n_input, { modelValue: metadata.value, "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => metadata.value = $event), type: "textarea", name: "metadata", rows: 4, "data-test-id": "sso-provider-xml" }, null, 8, ["modelValue"]), createBaseVNode("small", null, toDisplayString(unref(i18n).baseText("settings.sso.settings.ips.xml.help")), 1) ])) : createCommentVNode("", true), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ unref(ssoStore).isEnterpriseSamlEnabled ? (openBlock(), createBlock(_component_n8n_tooltip, { key: 0, disabled: unref(ssoStore).isSamlLoginEnabled || ssoSettingsSaved.value }, { content: withCtx(() => [ createBaseVNode("span", null, toDisplayString(unref(i18n).baseText("settings.sso.activation.tooltip")), 1) ]), default: withCtx(() => [ createVNode(_component_el_switch, { modelValue: unref(ssoStore).isSamlLoginEnabled, "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => unref(ssoStore).isSamlLoginEnabled = $event), "data-test-id": "sso-toggle", disabled: isToggleSsoDisabled.value, class: normalizeClass(_ctx.$style.switch), "inactive-text": ssoActivatedLabel.value }, null, 8, ["modelValue", "disabled", "class", "inactive-text"]) ]), _: 1 }, 8, ["disabled"])) : createCommentVNode("", true) ], 2) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.buttons) }, [ createVNode(_component_n8n_button, { disabled: !isSaveEnabled.value, size: "large", "data-test-id": "sso-save", onClick: onSave }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(i18n).baseText("settings.sso.settings.save")), 1) ]), _: 1 }, 8, ["disabled"]), createVNode(_component_n8n_button, { disabled: !isTestEnabled.value, size: "large", type: "tertiary", "data-test-id": "sso-test", onClick: onTest }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(i18n).baseText("settings.sso.settings.test")), 1) ]), _: 1 }, 8, ["disabled"]) ], 2), createBaseVNode("footer", { class: normalizeClass(_ctx.$style.footer) }, toDisplayString(unref(i18n).baseText("settings.sso.settings.footer.hint")), 3) ])) : (openBlock(), createBlock(_component_n8n_action_box, { key: 1, "data-test-id": "sso-content-unlicensed", class: normalizeClass(_ctx.$style.actionBox), description: unref(i18n).baseText("settings.sso.actionBox.description"), "button-text": unref(i18n).baseText("settings.sso.actionBox.buttonText"), "onClick:button": goToUpgrade }, { heading: withCtx(() => [ createBaseVNode("span", null, toDisplayString(unref(i18n).baseText("settings.sso.actionBox.title")), 1) ]), _: 1 }, 8, ["class", "description", "button-text"])) ])) : createCommentVNode("", true), authProtocol.value === unref(SupportedProtocols).OIDC ? (openBlock(), createElementBlock("div", _hoisted_8, [ unref(ssoStore).isEnterpriseOidcEnabled ? (openBlock(), createElementBlock("div", _hoisted_9, [ createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ _cache[10] || (_cache[10] = createBaseVNode("label", null, "Redirect URL", -1)), createVNode(CopyInput, { value: unref(ssoStore).oidc.callbackUrl, "copy-button-text": unref(i18n).baseText("generic.clickToCopy"), "toast-title": "Redirect URL copied to clipboard" }, null, 8, ["value", "copy-button-text"]), _cache[11] || (_cache[11] = createBaseVNode("small", null, "Copy the Redirect URL to configure your OIDC provider ", -1)) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ _cache[12] || (_cache[12] = createBaseVNode("label", null, "Discovery Endpoint", -1)), createVNode(_component_N8nInput, { "model-value": discoveryEndpoint.value, type: "text", "data-test-id": "oidc-discovery-endpoint", placeholder: "https://accounts.google.com/.well-known/openid-configuration", "onUpdate:modelValue": _cache[5] || (_cache[5] = (v) => discoveryEndpoint.value = v) }, null, 8, ["model-value"]), _cache[13] || (_cache[13] = createBaseVNode("small", null, "Paste here your discovery endpoint", -1)) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ _cache[14] || (_cache[14] = createBaseVNode("label", null, "Client ID", -1)), createVNode(_component_N8nInput, { "model-value": clientId.value, type: "text", "data-test-id": "oidc-client-id", "onUpdate:modelValue": _cache[6] || (_cache[6] = (v) => clientId.value = v) }, null, 8, ["model-value"]), _cache[15] || (_cache[15] = createBaseVNode("small", null, "The client ID you received when registering your application with your provider", -1)) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ _cache[16] || (_cache[16] = createBaseVNode("label", null, "Client Secret", -1)), createVNode(_component_N8nInput, { "model-value": clientSecret.value, type: "password", "data-test-id": "oidc-client-secret", "onUpdate:modelValue": _cache[7] || (_cache[7] = (v) => clientSecret.value = v) }, null, 8, ["model-value"]), _cache[17] || (_cache[17] = createBaseVNode("small", null, "The client Secret you received when registering your application with your provider", -1)) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.group) }, [ createVNode(_component_el_switch, { modelValue: unref(ssoStore).isOidcLoginEnabled, "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => unref(ssoStore).isOidcLoginEnabled = $event), "data-test-id": "sso-oidc-toggle", class: normalizeClass(_ctx.$style.switch), "inactive-text": oidcActivatedLabel.value }, null, 8, ["modelValue", "class", "inactive-text"]) ], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.buttons) }, [ createVNode(_component_n8n_button, { "data-test-id": "sso-oidc-save", size: "large", disabled: cannotSaveOidcSettings.value, onClick: onOidcSettingsSave }, { default: withCtx(() => [ createTextVNode(toDisplayString(unref(i18n).baseText("settings.sso.settings.save")), 1) ]), _: 1 }, 8, ["disabled"]) ], 2) ])) : (openBlock(), createBlock(_component_n8n_action_box, { key: 1, "data-test-id": "sso-content-unlicensed", class: normalizeClass(_ctx.$style.actionBox), "button-text": unref(i18n).baseText("settings.sso.actionBox.buttonText"), "onClick:button": goToUpgrade }, { heading: withCtx(() => [ createBaseVNode("span", null, toDisplayString(unref(i18n).baseText("settings.sso.actionBox.title")), 1) ]), _: 1 }, 8, ["class", "button-text"])) ])) : createCommentVNode("", true) ]); }; } }); const heading = "_heading_1ftgg_123"; const buttons = "_buttons_1ftgg_133"; const group = "_group_1ftgg_142"; const actionBox = "_actionBox_1ftgg_158"; const footer = "_footer_1ftgg_162"; const style0 = { heading, "switch": "_switch_1ftgg_127", buttons, group, actionBox, footer }; const cssModules = { "$style": style0 }; const SettingsSso = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]); export { SettingsSso as default };