import React, { useEffect, useState } from "react"; import { Modal, Form, Input, Button as Button2, Select, message } from "antd"; import { Text, TextInput } from "@tremor/react"; import { getSSOSettings, updateSSOSettings } from "./networking"; interface SSOModalsProps { isAddSSOModalVisible: boolean; isInstructionsModalVisible: boolean; handleAddSSOOk: () => void; handleAddSSOCancel: () => void; handleShowInstructions: (formValues: Record) => void; handleInstructionsOk: () => void; handleInstructionsCancel: () => void; form: any; // Replace with proper Form type if available accessToken: string | null; ssoConfigured?: boolean; // Add optional prop to indicate if SSO is configured } const ssoProviderLogoMap: Record = { google: "https://artificialanalysis.ai/img/logos/google_small.svg", microsoft: "https://upload.wikimedia.org/wikipedia/commons/a/a8/Microsoft_Azure_Logo.svg", okta: "https://www.okta.com/sites/default/files/Okta_Logo_BrightBlue_Medium.png", generic: "", }; // Define the SSO provider configuration type interface SSOProviderConfig { envVarMap: Record; fields: Array<{ label: string; name: string; placeholder?: string; }>; } // Define configurations for each SSO provider const ssoProviderConfigs: Record = { google: { envVarMap: { google_client_id: 'GOOGLE_CLIENT_ID', google_client_secret: 'GOOGLE_CLIENT_SECRET', }, fields: [ { label: 'GOOGLE CLIENT ID', name: 'google_client_id' }, { label: 'GOOGLE CLIENT SECRET', name: 'google_client_secret' }, ], }, microsoft: { envVarMap: { microsoft_client_id: 'MICROSOFT_CLIENT_ID', microsoft_client_secret: 'MICROSOFT_CLIENT_SECRET', microsoft_tenant: 'MICROSOFT_TENANT', }, fields: [ { label: 'MICROSOFT CLIENT ID', name: 'microsoft_client_id' }, { label: 'MICROSOFT CLIENT SECRET', name: 'microsoft_client_secret' }, { label: 'MICROSOFT TENANT', name: 'microsoft_tenant' }, ], }, okta: { envVarMap: { generic_client_id: 'GENERIC_CLIENT_ID', generic_client_secret: 'GENERIC_CLIENT_SECRET', generic_authorization_endpoint: 'GENERIC_AUTHORIZATION_ENDPOINT', generic_token_endpoint: 'GENERIC_TOKEN_ENDPOINT', generic_userinfo_endpoint: 'GENERIC_USERINFO_ENDPOINT', }, fields: [ { label: 'GENERIC CLIENT ID', name: 'generic_client_id' }, { label: 'GENERIC CLIENT SECRET', name: 'generic_client_secret' }, { label: 'AUTHORIZATION ENDPOINT', name: 'generic_authorization_endpoint', placeholder: 'https://your-okta-domain/authorize' }, { label: 'TOKEN ENDPOINT', name: 'generic_token_endpoint', placeholder: 'https://your-okta-domain/token' }, { label: 'USERINFO ENDPOINT', name: 'generic_userinfo_endpoint', placeholder: 'https://your-okta-domain/userinfo' }, ], }, generic: { envVarMap: { generic_client_id: 'GENERIC_CLIENT_ID', generic_client_secret: 'GENERIC_CLIENT_SECRET', generic_authorization_endpoint: 'GENERIC_AUTHORIZATION_ENDPOINT', generic_token_endpoint: 'GENERIC_TOKEN_ENDPOINT', generic_userinfo_endpoint: 'GENERIC_USERINFO_ENDPOINT', }, fields: [ { label: 'GENERIC CLIENT ID', name: 'generic_client_id' }, { label: 'GENERIC CLIENT SECRET', name: 'generic_client_secret' }, { label: 'AUTHORIZATION ENDPOINT', name: 'generic_authorization_endpoint' }, { label: 'TOKEN ENDPOINT', name: 'generic_token_endpoint' }, { label: 'USERINFO ENDPOINT', name: 'generic_userinfo_endpoint' }, ], }, }; const SSOModals: React.FC = ({ isAddSSOModalVisible, isInstructionsModalVisible, handleAddSSOOk, handleAddSSOCancel, handleShowInstructions, handleInstructionsOk, handleInstructionsCancel, form, accessToken, ssoConfigured = false, // Default to false if not provided }) => { const [isClearConfirmModalVisible, setIsClearConfirmModalVisible] = useState(false); // Load existing SSO settings when modal opens useEffect(() => { const loadSSOSettings = async () => { if (isAddSSOModalVisible && accessToken) { try { const ssoData = await getSSOSettings(accessToken); console.log("Raw SSO data received:", ssoData); // Debug log if (ssoData && ssoData.values) { console.log("SSO values:", ssoData.values); // Debug log console.log("user_email from API:", ssoData.values.user_email); // Debug log // Determine which SSO provider is configured let selectedProvider = null; if (ssoData.values.google_client_id) { selectedProvider = 'google'; } else if (ssoData.values.microsoft_client_id) { selectedProvider = 'microsoft'; } else if (ssoData.values.generic_client_id) { // Check if it looks like Okta based on endpoints if (ssoData.values.generic_authorization_endpoint?.includes('okta') || ssoData.values.generic_authorization_endpoint?.includes('auth0')) { selectedProvider = 'okta'; } else { selectedProvider = 'generic'; } } // Set form values with existing data const formValues = { sso_provider: selectedProvider, proxy_base_url: ssoData.values.proxy_base_url, user_email: ssoData.values.user_email, ...ssoData.values, }; console.log("Setting form values:", formValues); // Debug log // Clear form first, then set values with a small delay to ensure proper initialization form.resetFields(); setTimeout(() => { form.setFieldsValue(formValues); console.log("Form values set, current form values:", form.getFieldsValue()); // Debug log }, 100); } } catch (error) { console.error("Failed to load SSO settings:", error); } } }; loadSSOSettings(); }, [isAddSSOModalVisible, accessToken, form]); // Enhanced form submission handler const handleFormSubmit = async (formValues: Record) => { if (!accessToken) { message.error("No access token available"); return; } try { // Save SSO settings using the new API await updateSSOSettings(accessToken, formValues); // Continue with the original flow (show instructions) handleShowInstructions(formValues); } catch (error) { console.error("Failed to save SSO settings:", error); message.error("Failed to save SSO settings"); } }; // Handle clearing SSO settings const handleClearSSO = async () => { if (!accessToken) { message.error("No access token available"); return; } try { // Clear all SSO settings by sending empty values const clearSettings = { google_client_id: '', google_client_secret: '', microsoft_client_id: '', microsoft_client_secret: '', microsoft_tenant: '', generic_client_id: '', generic_client_secret: '', generic_authorization_endpoint: '', generic_token_endpoint: '', generic_userinfo_endpoint: '', proxy_base_url: '', user_email: '', sso_provider: '', }; await updateSSOSettings(accessToken, clearSettings); // Clear the form form.resetFields(); // Close the confirmation modal setIsClearConfirmModalVisible(false); // Close the main SSO modal and trigger refresh handleAddSSOOk(); message.success("SSO settings cleared successfully"); } catch (error) { console.error("Failed to clear SSO settings:", error); message.error("Failed to clear SSO settings"); } }; // Helper function to render provider fields const renderProviderFields = (provider: string) => { const config = ssoProviderConfigs[provider]; if (!config) return null; return config.fields.map((field) => ( {field.name.includes('client') ? ( ) : ( )} )); }; return ( <>
<> prevValues.sso_provider !== currentValues.sso_provider} > {({ getFieldValue }) => { const provider = getFieldValue('sso_provider'); return provider ? renderProviderFields(provider) : null; }}
{ssoConfigured && ( setIsClearConfirmModalVisible(true)} style={{ backgroundColor: '#6366f1', borderColor: '#6366f1', color: 'white' }} onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = '#5558eb'; e.currentTarget.style.borderColor = '#5558eb'; }} onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = '#6366f1'; e.currentTarget.style.borderColor = '#6366f1'; }} > Clear )} Save
{/* Clear Confirmation Modal */} setIsClearConfirmModalVisible(false)} okText="Yes, Clear" cancelText="Cancel" okButtonProps={{ danger: true, style: { backgroundColor: '#dc2626', borderColor: '#dc2626' } }} >

Are you sure you want to clear all SSO settings? This action cannot be undone.

Users will no longer be able to login using SSO after this change.

Follow these steps to complete the SSO setup:

1. DO NOT Exit this TAB 2. Open a new tab, visit your proxy base url 3. Confirm your SSO is configured correctly and you can login on the new Tab 4. If Step 3 is successful, you can close this tab
Done
); }; export { ssoProviderConfigs }; // Export for use in other components export default SSOModals;