From a473b360ef234ae4fe675c48bb56ed35ab270748 Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Tue, 5 Mar 2024 16:57:02 +0000 Subject: [PATCH] New OIDC fed (#2336) * add WellKnownURLs * Fix translation keys * Update dependencies and add IdP Configuration * Update common.json with new translations * wip * Update @boxyhq/internal-ui version to 0.0.5 * add internal ui folder * Fix imports and build * Refactor internal-ui package structure * wip shared UI * Fix the build * WIP * Add new components and hooks for directory sync * WIP * lint fix * updated swr * WIP * users * Refactor shared components and fix API endpoints*** ***Update directory user page and add new federated SAML app * Fix lint * wip * Add new files and update existing files * Refactor DirectoryGroups and DirectoryInfo components * Update localization strings for directory UI * Update Google Auth URL description in common.json * Refactor directory tab and add delete functionality to webhook logs * IdP selection screen changes * Delete unused files and update dependencies * Fix column declaration * Add internal-ui/dist to .gitignore * Update page limit and add new dependencies * wip * Refactor directory search in user API endpoint * wip * Refactor directory retrieval logic in user and group API handlers * Add API endpoints for retrieving webhook events * check app's redirectUrl, TODO: save app info into session to read later * Add query parameters to API URLs in DirectoryGroups * working saml login via IdP select. TODO: oidc login via IdP select and saml + oidc login with 1 connection * oidc IdP working with selection * working oidc fed -> saml flow * Add Google authorization status badge and handle pagination in FederatedSAMLApps * Add router prop to AppsList component and update page header titles * UI changes * updated peer-deps * Add new files and export functions * Remove unused router prop * Add PencilIcon to FederatedSAMLApps * updated federated app creation page * updated federated app edit page * Refactor FederatedSAMLApps and NewFederatedSAMLApp components * lint fix * lint fix * updated package-lock * add jose npm to dev dep * added missing strings * added missing strings * locale strings fix * locale strings cleanup * tweaks to icon imports * replaced textarea with list of inputs for Federated Apps redirect url * update package-lock * Add prepublish step * Build and publish npm and internal ui * Refactor install step * Run npm install (for local) inside internal ui automatically using prepare * Remove eslint setup for internal-ui * updated package-lock * Add `--legacy-peer-deps` to prevent installing peer dependencies * Fix the types import path * wip * wip * Fix the types * Format * Update package-lock * Cleanup * Try adding jose library version 5.2.2 * allow selective subdomain globbing * removed duplicate jose lib * updated package-lock * updated swagger doc * SAML Federation -> Identity Federation * fixed locale strings * turn off autocomplete for tags input --------- Co-authored-by: Kiran K Co-authored-by: Aswin V --- check-locale.js | 3 - components/Sidebar.tsx | 2 +- components/connection/utils.tsx | 3 +- ee/federated-saml/api/admin/[id]/index.ts | 6 +- ee/federated-saml/api/admin/index.ts | 4 +- ee/federated-saml/pages/index.tsx | 6 +- internal-ui/src/dsync/DirectoryGroups.tsx | 2 +- internal-ui/src/dsync/DirectoryUsers.tsx | 2 +- .../src/dsync/DirectoryWebhookLogs.tsx | 2 +- internal-ui/src/federated-saml/Edit.tsx | 102 ++++++++--- .../federated-saml/EditFederatedSAMLApp.tsx | 23 ++- .../src/federated-saml/FederatedSAMLApps.tsx | 11 +- .../federated-saml/NewFederatedSAMLApp.tsx | 169 ++++++++++++------ internal-ui/src/shared/ItemList.tsx | 73 ++++++++ internal-ui/src/types.ts | 4 + internal-ui/src/well-known/WellKnownURLs.tsx | 15 +- locales/en/common.json | 42 +++-- npm/package-lock.json | 44 +++-- npm/src/controller/oauth.ts | 84 ++++++++- npm/src/controller/oauth/allowed.ts | 15 +- npm/src/controller/sso-handler.ts | 41 +++-- npm/src/controller/utils.ts | 6 + npm/src/ee/federated-saml/app.ts | 110 ++++++++---- npm/src/ee/federated-saml/index.ts | 2 +- npm/src/ee/federated-saml/types.ts | 5 + npm/src/index.ts | 9 +- npm/test/federated-saml/app.test.ts | 10 +- pages/admin/retraced/projects/index.tsx | 3 +- pages/idp/select.tsx | 8 +- pages/setup/[token]/sso-connection/new.tsx | 2 +- swagger/swagger.json | 38 ++-- 31 files changed, 600 insertions(+), 246 deletions(-) create mode 100644 internal-ui/src/shared/ItemList.tsx diff --git a/check-locale.js b/check-locale.js index 9bbb83d58..df7339e92 100644 --- a/check-locale.js +++ b/check-locale.js @@ -8,7 +8,6 @@ const allStrings = {}; const localeFile = require('./locales/en/common.json'); const files = fs.readdirSync('./', { recursive: true, withFileTypes: true }); -//console.log('files:', files); let error = false; @@ -25,7 +24,6 @@ files.forEach((file) => { (fileContent.match(regExp) || []).forEach((match) => { const id = match.replace("t('", '').replace("'", ''); - // console.log('match:', match); allStrings[id] = true; if (!localeFile[id]) { error = true; @@ -35,7 +33,6 @@ files.forEach((file) => { (fileContent.match(altRegExp) || []).forEach((match) => { const id = match.replace("i18nKey='", '').replace("'", ''); - // console.log('match:', match, id); allStrings[id] = true; if (!localeFile[id]) { error = true; diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx index 739e4b29f..62d9846fd 100644 --- a/components/Sidebar.tsx +++ b/components/Sidebar.tsx @@ -10,7 +10,7 @@ import SSOLogo from '@components/logo/SSO'; import DSyncLogo from '@components/logo/DSync'; import AuditLogsLogo from '@components/logo/AuditLogs'; import Vault from '@components/logo/Vault'; -import { Cog8ToothIcon } from '@heroicons/react/24/outline'; +import Cog8ToothIcon from '@heroicons/react/24/outline/Cog8ToothIcon'; type SidebarProps = { isOpen: boolean; diff --git a/components/connection/utils.tsx b/components/connection/utils.tsx index 4c1652550..eafead97e 100644 --- a/components/connection/utils.tsx +++ b/components/connection/utils.tsx @@ -2,7 +2,8 @@ import { ButtonLink } from '@components/ButtonLink'; import { Dispatch, FormEvent, SetStateAction, useMemo, useState } from 'react'; import { EditViewOnlyFields, getCommonFields } from './fieldCatalog'; import { CopyToClipboardButton } from '@components/ClipboardButton'; -import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'; +import EyeIcon from '@heroicons/react/24/outline/EyeIcon'; +import EyeSlashIcon from '@heroicons/react/24/outline/EyeSlashIcon'; import { IconButton } from '@components/IconButton'; import { useTranslation } from 'next-i18next'; diff --git a/ee/federated-saml/api/admin/[id]/index.ts b/ee/federated-saml/api/admin/[id]/index.ts index a6b9b55dd..4478f80ec 100644 --- a/ee/federated-saml/api/admin/[id]/index.ts +++ b/ee/federated-saml/api/admin/[id]/index.ts @@ -26,7 +26,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { } }; -// Get SAML Federation app by id +// Get Identity Federation app by id const handleGET = async (req: NextApiRequest, res: NextApiResponse) => { const { samlFederatedController } = await jackson(); @@ -43,7 +43,7 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => { }); }; -// Update SAML Federation app +// Update Identity Federation app const handlePATCH = async (req: NextApiRequest, res: NextApiResponse) => { const { samlFederatedController } = await jackson(); @@ -52,7 +52,7 @@ const handlePATCH = async (req: NextApiRequest, res: NextApiResponse) => { return res.status(200).json({ data: updatedApp }); }; -// Delete the SAML Federation app +// Delete the Identity Federation app const handleDELETE = async (req: NextApiRequest, res: NextApiResponse) => { const { samlFederatedController } = await jackson(); diff --git a/ee/federated-saml/api/admin/index.ts b/ee/federated-saml/api/admin/index.ts index 6b0dabd93..47a6c867f 100644 --- a/ee/federated-saml/api/admin/index.ts +++ b/ee/federated-saml/api/admin/index.ts @@ -22,7 +22,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { } }; -// Create new SAML Federation app +// Create new Identity Federation app const handlePOST = async (req: NextApiRequest, res: NextApiResponse) => { const { samlFederatedController } = await jackson(); @@ -31,7 +31,7 @@ const handlePOST = async (req: NextApiRequest, res: NextApiResponse) => { return res.status(201).json({ data: app }); }; -// Get SAML Federation apps +// Get Identity Federation apps const handleGET = async (req: NextApiRequest, res: NextApiResponse) => { const { samlFederatedController } = await jackson(); diff --git a/ee/federated-saml/pages/index.tsx b/ee/federated-saml/pages/index.tsx index 1948772fb..15dc74a1c 100644 --- a/ee/federated-saml/pages/index.tsx +++ b/ee/federated-saml/pages/index.tsx @@ -11,7 +11,11 @@ const AppsList = ({ hasValidLicense }: { hasValidLicense: boolean }) => { router.push(`/admin/federated-saml/${app.id}/edit`)} - actions={{ newApp: '/admin/federated-saml/new', idpConfiguration: '/.well-known/idp-configuration' }} + actions={{ + newApp: '/admin/federated-saml/new', + samlConfiguration: '/.well-known/idp-configuration', + oidcConfiguration: '/.well-known/openid-configuration', + }} /> ); }; diff --git a/internal-ui/src/dsync/DirectoryGroups.tsx b/internal-ui/src/dsync/DirectoryGroups.tsx index 3161b8808..a9e854449 100644 --- a/internal-ui/src/dsync/DirectoryGroups.tsx +++ b/internal-ui/src/dsync/DirectoryGroups.tsx @@ -1,6 +1,6 @@ import useSWR from 'swr'; import { useTranslation } from 'next-i18next'; -import { EyeIcon } from '@heroicons/react/24/outline'; +import EyeIcon from '@heroicons/react/24/outline/EyeIcon'; import type { Group } from '../types'; import { fetcher, addQueryParamsToPath } from '../utils'; import { DirectoryTab } from '../dsync'; diff --git a/internal-ui/src/dsync/DirectoryUsers.tsx b/internal-ui/src/dsync/DirectoryUsers.tsx index fb48e9c41..b79a50cfe 100644 --- a/internal-ui/src/dsync/DirectoryUsers.tsx +++ b/internal-ui/src/dsync/DirectoryUsers.tsx @@ -1,6 +1,6 @@ import useSWR from 'swr'; import { useTranslation } from 'next-i18next'; -import { EyeIcon } from '@heroicons/react/24/outline'; +import EyeIcon from '@heroicons/react/24/outline/EyeIcon'; import type { User } from '../types'; import { addQueryParamsToPath, fetcher } from '../utils'; import { DirectoryTab } from '../dsync'; diff --git a/internal-ui/src/dsync/DirectoryWebhookLogs.tsx b/internal-ui/src/dsync/DirectoryWebhookLogs.tsx index 817324dc2..96c72d3cd 100644 --- a/internal-ui/src/dsync/DirectoryWebhookLogs.tsx +++ b/internal-ui/src/dsync/DirectoryWebhookLogs.tsx @@ -1,7 +1,7 @@ import useSWR from 'swr'; import { useState } from 'react'; import { useTranslation } from 'next-i18next'; -import { EyeIcon } from '@heroicons/react/24/outline'; +import EyeIcon from '@heroicons/react/24/outline/EyeIcon'; import type { WebhookEventLog } from '../types'; import { fetcher, addQueryParamsToPath } from '../utils'; import { DirectoryTab } from '../dsync'; diff --git a/internal-ui/src/federated-saml/Edit.tsx b/internal-ui/src/federated-saml/Edit.tsx index ef33c3866..f46ead80c 100644 --- a/internal-ui/src/federated-saml/Edit.tsx +++ b/internal-ui/src/federated-saml/Edit.tsx @@ -5,8 +5,9 @@ import { useTranslation } from 'next-i18next'; import { useFormik } from 'formik'; import { Card } from '../shared'; import { defaultHeaders } from '../utils'; +import { ItemList } from '../shared/ItemList'; -type EditApp = Pick; +type EditApp = Pick; export const Edit = ({ app, @@ -23,12 +24,16 @@ export const Edit = ({ }) => { const { t } = useTranslation('common'); + const connectionIsOIDC = app.type === 'oidc'; + const connectionIsSAML = !connectionIsOIDC; + const formik = useFormik({ enableReinitialize: true, initialValues: { name: app.name || '', acsUrl: app.acsUrl || '', tenants: app.tenants || [], + redirectUrl: app.redirectUrl || [], }, onSubmit: async (values) => { const rawResponse = await fetch(urls.patch, { @@ -92,34 +97,74 @@ export const Edit = ({ /> )} - -