diff --git a/frontend/src/const.ts b/frontend/src/const.ts index af52b68af..806755f38 100644 --- a/frontend/src/const.ts +++ b/frontend/src/const.ts @@ -61,7 +61,8 @@ export const leaveConfirmDefaultMessage = export enum SessionStorageKeys { CLI_TERMINAL_TOKEN = "CLI_TERMINAL_TOKEN", ORG_LOGIN_SUCCESS_REDIRECT_URL = "ORG_LOGIN_SUCCESS_REDIRECT_URL", - AUTH_CONSENT = "AUTH_CONSENT" + AUTH_CONSENT = "AUTH_CONSENT", + MFA_TEMP_TOKEN = "MFA_TEMP_TOKEN" } export const secretTagsColors = [ diff --git a/frontend/src/pages/auth/SelectOrgPage/SelectOrgSection.tsx b/frontend/src/pages/auth/SelectOrgPage/SelectOrgSection.tsx index a15bab287..98633e390 100644 --- a/frontend/src/pages/auth/SelectOrgPage/SelectOrgSection.tsx +++ b/frontend/src/pages/auth/SelectOrgPage/SelectOrgSection.tsx @@ -47,6 +47,7 @@ export const SelectOrganizationSection = () => { const orgId = queryParams.get("org_id"); const callbackPort = queryParams.get("callback_port"); const isAdminLogin = queryParams.get("is_admin_login") === "true"; + const mfaPending = queryParams.get("mfa_pending") === "true"; const defaultSelectedOrg = organizations.data?.find((org) => org.id === orgId); const logout = useLogoutUser(true); @@ -236,10 +237,22 @@ export const SelectOrganizationSection = () => { }, [organizations.isPending, organizations.data]); useEffect(() => { + if (mfaPending && defaultSelectedOrg) { + const storedMfaToken = sessionStorage.getItem(SessionStorageKeys.MFA_TEMP_TOKEN); + if (storedMfaToken) { + sessionStorage.removeItem(SessionStorageKeys.MFA_TEMP_TOKEN); + SecurityClient.setMfaToken(storedMfaToken); + setIsInitialOrgCheckLoading(false); + toggleShowMfa.on(); + setMfaSuccessCallback(() => () => handleSelectOrganization(defaultSelectedOrg)); + return; + } + } + if (defaultSelectedOrg) { handleSelectOrganization(defaultSelectedOrg); } - }, [defaultSelectedOrg]); + }, [defaultSelectedOrg, mfaPending]); if ( userLoading || diff --git a/frontend/src/pages/auth/SelectOrgPage/route.tsx b/frontend/src/pages/auth/SelectOrgPage/route.tsx index 27ad4bb94..f20fda1f3 100644 --- a/frontend/src/pages/auth/SelectOrgPage/route.tsx +++ b/frontend/src/pages/auth/SelectOrgPage/route.tsx @@ -8,7 +8,8 @@ export const SelectOrganizationPageQueryParams = z.object({ org_id: z.string().optional().catch(""), callback_port: z.coerce.number().optional().catch(undefined), is_admin_login: z.boolean().optional().catch(false), - force: z.boolean().optional() + force: z.boolean().optional(), + mfa_pending: z.boolean().optional().catch(false) }); export const Route = createFileRoute("/_restrict-login-signup/login/select-organization")({ @@ -16,7 +17,12 @@ export const Route = createFileRoute("/_restrict-login-signup/login/select-organ validateSearch: zodValidator(SelectOrganizationPageQueryParams), search: { middlewares: [ - stripSearchParams({ org_id: "", callback_port: undefined, is_admin_login: false }) + stripSearchParams({ + org_id: "", + callback_port: undefined, + is_admin_login: false, + mfa_pending: false + }) ] } }); diff --git a/frontend/src/pages/middlewares/inject-org-details.tsx b/frontend/src/pages/middlewares/inject-org-details.tsx index a9ada71d0..698718184 100644 --- a/frontend/src/pages/middlewares/inject-org-details.tsx +++ b/frontend/src/pages/middlewares/inject-org-details.tsx @@ -1,6 +1,7 @@ import { createFileRoute, isRedirect, redirect } from "@tanstack/react-router"; import SecurityClient from "@app/components/utilities/SecurityClient"; +import { SessionStorageKeys } from "@app/const"; import { authKeys, fetchAuthToken, selectOrganization } from "@app/hooks/api/auth/queries"; import { fetchOrganizationById, organizationKeys } from "@app/hooks/api/organization/queries"; import { projectKeys } from "@app/hooks/api/projects"; @@ -28,9 +29,10 @@ export const Route = createFileRoute("/_authenticate/_inject-org-details")({ const { token, isMfaEnabled } = await selectOrganization({ organizationId: urlOrgId }); if (isMfaEnabled) { + sessionStorage.setItem(SessionStorageKeys.MFA_TEMP_TOKEN, token); throw redirect({ to: "/login/select-organization", - search: { org_id: urlOrgId } + search: { org_id: urlOrgId, mfa_pending: true } }); } diff --git a/frontend/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersSection.tsx b/frontend/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersSection.tsx index 6a4d93141..3946a3859 100644 --- a/frontend/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersSection.tsx +++ b/frontend/src/pages/organization/AccessManagementPage/components/OrgMembersTab/components/OrgMembersSection/OrgMembersSection.tsx @@ -242,7 +242,7 @@ export const OrgMembersSection = () => { isOpen={popUp.addMemberToSubOrg.isOpen} onOpenChange={(isOpen) => handlePopUpToggle("addMemberToSubOrg", isOpen)} > - + handlePopUpClose("addMemberToSubOrg")} />