diff --git a/backend/src/services/org/org-service.ts b/backend/src/services/org/org-service.ts index f5e15bbda..27e62304d 100644 --- a/backend/src/services/org/org-service.ts +++ b/backend/src/services/org/org-service.ts @@ -270,11 +270,26 @@ export const orgServiceFactory = ({ orgId, data: { name, slug, authEnforced, scimEnabled, defaultMembershipRoleSlug, enforceMfa } }: TUpdateOrgDTO) => { + const appCfg = getConfig(); const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); const plan = await licenseService.getPlan(orgId); + if (enforceMfa !== undefined) { + if (!plan.enforceMfa) { + throw new BadRequestError({ + message: "Failed to enforce user MFA due to plan restriction. Upgrade plan to enforce/un-enforce MFA." + }); + } + + if (!appCfg.isSmtpConfigured) { + throw new BadRequestError({ + message: "Failed to enforce user MFA due to missing instance SMTP configuration." + }); + } + } + if (authEnforced !== undefined) { if (!plan?.samlSSO || !plan.oidcSSO) throw new BadRequestError({ diff --git a/frontend/src/pages/login/select-organization.tsx b/frontend/src/pages/login/select-organization.tsx index d4b3236e2..69957a4f7 100644 --- a/frontend/src/pages/login/select-organization.tsx +++ b/frontend/src/pages/login/select-organization.tsx @@ -15,9 +15,13 @@ import { IsCliLoginSuccessful } from "@app/components/utilities/attemptCliLogin" import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button, Spinner } from "@app/components/v2"; import { SessionStorageKeys } from "@app/const"; -import { useUser } from "@app/context"; import { useToggle } from "@app/hooks"; -import { useGetOrganizations, useLogoutUser, useSelectOrganization } from "@app/hooks/api"; +import { + useGetOrganizations, + useGetUser, + useLogoutUser, + useSelectOrganization +} from "@app/hooks/api"; import { UserAgentType } from "@app/hooks/api/auth/types"; import { Organization } from "@app/hooks/api/types"; import { AuthMethod } from "@app/hooks/api/users/types"; @@ -40,9 +44,9 @@ export default function LoginPage() { const organizations = useGetOrganizations(); const selectOrg = useSelectOrganization(); - - const { user, isLoading: userLoading } = useUser(); + const { data: user, isLoading: userLoading } = useGetUser(); const [shouldShowMfa, toggleShowMfa] = useToggle(false); + const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {}); const queryParams = new URLSearchParams(window.location.search); @@ -104,7 +108,7 @@ export default function LoginPage() { let error: string | null = null; if (!privateKey) error = "Private key not found"; - if (!user.email) error = "User email not found"; + if (!user?.email) error = "User email not found"; if (!token) error = "No token found"; if (error) { @@ -117,7 +121,7 @@ export default function LoginPage() { const payload = { JTWToken: token, - email: user.email, + email: user?.email, privateKey } as IsCliLoginSuccessful["loginResponse"];