mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 19:28:51 +00:00
misc: added org mfa settings update and other fixes
This commit is contained in:
@@ -108,7 +108,8 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
|||||||
tokenVersionId: tokenVersion.id,
|
tokenVersionId: tokenVersion.id,
|
||||||
accessVersion: tokenVersion.accessVersion,
|
accessVersion: tokenVersion.accessVersion,
|
||||||
organizationId: decodedToken.organizationId,
|
organizationId: decodedToken.organizationId,
|
||||||
isMfaVerified: decodedToken.isMfaVerified
|
isMfaVerified: decodedToken.isMfaVerified,
|
||||||
|
mfaMethod: decodedToken.mfaMethod
|
||||||
},
|
},
|
||||||
appCfg.AUTH_SECRET,
|
appCfg.AUTH_SECRET,
|
||||||
{ expiresIn: appCfg.JWT_AUTH_LIFETIME }
|
{ expiresIn: appCfg.JWT_AUTH_LIFETIME }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
|||||||
import { getLastMidnightDateISO } from "@app/lib/fn";
|
import { getLastMidnightDateISO } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
import { ActorType, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
import { integrationAuthPubSchema } from "../sanitizedSchemas";
|
import { integrationAuthPubSchema } from "../sanitizedSchemas";
|
||||||
|
|
||||||
@@ -259,7 +259,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
message: "Membership role must be a valid slug"
|
message: "Membership role must be a valid slug"
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
enforceMfa: z.boolean().optional()
|
enforceMfa: z.boolean().optional(),
|
||||||
|
selectedMfaMethod: z.nativeEnum(MfaMethod).optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
|||||||
@@ -396,7 +396,8 @@ export const authLoginServiceFactory = ({
|
|||||||
userAgent,
|
userAgent,
|
||||||
ip: ipAddress,
|
ip: ipAddress,
|
||||||
organizationId,
|
organizationId,
|
||||||
isMfaVerified: decodedToken.isMfaVerified
|
isMfaVerified: decodedToken.isMfaVerified,
|
||||||
|
mfaMethod: decodedToken.mfaMethod
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ export type AuthModeRefreshJwtTokenPayload = {
|
|||||||
refreshVersion: number;
|
refreshVersion: number;
|
||||||
organizationId?: string;
|
organizationId?: string;
|
||||||
isMfaVerified?: boolean;
|
isMfaVerified?: boolean;
|
||||||
|
mfaMethod?: MfaMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AuthModeProviderJwtTokenPayload = {
|
export type AuthModeProviderJwtTokenPayload = {
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ export const orgServiceFactory = ({
|
|||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
orgId,
|
orgId,
|
||||||
data: { name, slug, authEnforced, scimEnabled, defaultMembershipRoleSlug, enforceMfa }
|
data: { name, slug, authEnforced, scimEnabled, defaultMembershipRoleSlug, enforceMfa, selectedMfaMethod }
|
||||||
}: TUpdateOrgDTO) => {
|
}: TUpdateOrgDTO) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||||
@@ -333,7 +333,8 @@ export const orgServiceFactory = ({
|
|||||||
authEnforced,
|
authEnforced,
|
||||||
scimEnabled,
|
scimEnabled,
|
||||||
defaultMembershipRole,
|
defaultMembershipRole,
|
||||||
enforceMfa
|
enforceMfa,
|
||||||
|
selectedMfaMethod
|
||||||
});
|
});
|
||||||
if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` });
|
if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` });
|
||||||
return org;
|
return org;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TOrgPermission } from "@app/lib/types";
|
import { TOrgPermission } from "@app/lib/types";
|
||||||
|
|
||||||
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
|
import { ActorAuthMethod, ActorType, MfaMethod } from "../auth/auth-type";
|
||||||
|
|
||||||
export type TUpdateOrgMembershipDTO = {
|
export type TUpdateOrgMembershipDTO = {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -65,6 +65,7 @@ export type TUpdateOrgDTO = {
|
|||||||
scimEnabled: boolean;
|
scimEnabled: boolean;
|
||||||
defaultMembershipRoleSlug: string;
|
defaultMembershipRoleSlug: string;
|
||||||
enforceMfa: boolean;
|
enforceMfa: boolean;
|
||||||
|
selectedMfaMethod: MfaMethod;
|
||||||
}>;
|
}>;
|
||||||
} & TOrgPermission;
|
} & TOrgPermission;
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ export const useUpdateOrg = () => {
|
|||||||
slug,
|
slug,
|
||||||
orgId,
|
orgId,
|
||||||
defaultMembershipRoleSlug,
|
defaultMembershipRoleSlug,
|
||||||
enforceMfa
|
enforceMfa,
|
||||||
|
selectedMfaMethod
|
||||||
}) => {
|
}) => {
|
||||||
return apiRequest.patch(`/api/v1/organization/${orgId}`, {
|
return apiRequest.patch(`/api/v1/organization/${orgId}`, {
|
||||||
name,
|
name,
|
||||||
@@ -99,7 +100,8 @@ export const useUpdateOrg = () => {
|
|||||||
scimEnabled,
|
scimEnabled,
|
||||||
slug,
|
slug,
|
||||||
defaultMembershipRoleSlug,
|
defaultMembershipRoleSlug,
|
||||||
enforceMfa
|
enforceMfa,
|
||||||
|
selectedMfaMethod
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
import { IdentityMembershipOrg } from "@app/hooks/api/identities/types";
|
import { IdentityMembershipOrg } from "@app/hooks/api/identities/types";
|
||||||
|
|
||||||
|
import { MfaMethod } from "../auth/types";
|
||||||
|
|
||||||
export type Organization = {
|
export type Organization = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -12,6 +14,7 @@ export type Organization = {
|
|||||||
slug: string;
|
slug: string;
|
||||||
defaultMembershipRole: string;
|
defaultMembershipRole: string;
|
||||||
enforceMfa: boolean;
|
enforceMfa: boolean;
|
||||||
|
selectedMfaMethod?: MfaMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateOrgDTO = {
|
export type UpdateOrgDTO = {
|
||||||
@@ -22,6 +25,7 @@ export type UpdateOrgDTO = {
|
|||||||
slug?: string;
|
slug?: string;
|
||||||
defaultMembershipRoleSlug?: string;
|
defaultMembershipRoleSlug?: string;
|
||||||
enforceMfa?: boolean;
|
enforceMfa?: boolean;
|
||||||
|
selectedMfaMethod?: MfaMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BillingDetails = {
|
export type BillingDetails = {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ import {
|
|||||||
useLogoutUser,
|
useLogoutUser,
|
||||||
useSelectOrganization
|
useSelectOrganization
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { INTERNAL_KMS_KEY_ID } from "@app/hooks/api/kms/types";
|
import { INTERNAL_KMS_KEY_ID } from "@app/hooks/api/kms/types";
|
||||||
import { InfisicalProjectTemplate, useListProjectTemplates } from "@app/hooks/api/projectTemplates";
|
import { InfisicalProjectTemplate, useListProjectTemplates } from "@app/hooks/api/projectTemplates";
|
||||||
import { Workspace } from "@app/hooks/api/types";
|
import { Workspace } from "@app/hooks/api/types";
|
||||||
@@ -143,6 +144,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
const { data: projectFavorites } = useGetUserProjectFavorites(currentOrg?.id!);
|
const { data: projectFavorites } = useGetUserProjectFavorites(currentOrg?.id!);
|
||||||
const { mutateAsync: updateUserProjectFavorites } = useUpdateUserProjectFavorites();
|
const { mutateAsync: updateUserProjectFavorites } = useUpdateUserProjectFavorites();
|
||||||
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
||||||
|
const [requiredMfaMethod, setRequiredMfaMethod] = useState(MfaMethod.EMAIL);
|
||||||
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
||||||
|
|
||||||
const workspacesWithFaveProp = useMemo(
|
const workspacesWithFaveProp = useMemo(
|
||||||
@@ -214,12 +216,15 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const changeOrg = async (orgId: string) => {
|
const changeOrg = async (orgId: string) => {
|
||||||
const { token, isMfaEnabled } = await selectOrganization({
|
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({
|
||||||
organizationId: orgId
|
organizationId: orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
|
if (mfaMethod) {
|
||||||
|
setRequiredMfaMethod(mfaMethod);
|
||||||
|
}
|
||||||
toggleShowMfa.on();
|
toggleShowMfa.on();
|
||||||
setMfaSuccessCallback(() => () => changeOrg(orgId));
|
setMfaSuccessCallback(() => () => changeOrg(orgId));
|
||||||
return;
|
return;
|
||||||
@@ -365,6 +370,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
|||||||
<div className="flex max-h-screen min-h-screen flex-col items-center justify-center gap-2 overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
|
<div className="flex max-h-screen min-h-screen flex-col items-center justify-center gap-2 overflow-y-auto bg-gradient-to-tr from-mineshaft-600 via-mineshaft-800 to-bunker-700">
|
||||||
<Mfa
|
<Mfa
|
||||||
email={user.email as string}
|
email={user.email as string}
|
||||||
|
method={requiredMfaMethod}
|
||||||
successCallback={mfaSuccessCallback}
|
successCallback={mfaSuccessCallback}
|
||||||
closeMfa={() => toggleShowMfa.off()}
|
closeMfa={() => toggleShowMfa.off()}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { Button, Input, Spinner } from "@app/components/v2";
|
|||||||
import { SessionStorageKeys } from "@app/const";
|
import { SessionStorageKeys } from "@app/const";
|
||||||
import { useToggle } from "@app/hooks";
|
import { useToggle } from "@app/hooks";
|
||||||
import { useOauthTokenExchange, useSelectOrganization } from "@app/hooks/api";
|
import { useOauthTokenExchange, useSelectOrganization } from "@app/hooks/api";
|
||||||
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
import { fetchMyPrivateKey } from "@app/hooks/api/users/queries";
|
import { fetchMyPrivateKey } from "@app/hooks/api/users/queries";
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ export const PasswordStep = ({ providerAuthToken, email, password, setPassword }
|
|||||||
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
||||||
const { mutateAsync: oauthTokenExchange } = useOauthTokenExchange();
|
const { mutateAsync: oauthTokenExchange } = useOauthTokenExchange();
|
||||||
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
||||||
|
const [requiredMfaMethod, setRequiredMfaMethod] = useState(MfaMethod.EMAIL);
|
||||||
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
||||||
|
|
||||||
const { navigateToSelectOrganization } = useNavigateToSelectOrganization();
|
const { navigateToSelectOrganization } = useNavigateToSelectOrganization();
|
||||||
@@ -66,10 +68,13 @@ export const PasswordStep = ({ providerAuthToken, email, password, setPassword }
|
|||||||
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
||||||
if (organizationId) {
|
if (organizationId) {
|
||||||
const finishWithOrgWorkflow = async () => {
|
const finishWithOrgWorkflow = async () => {
|
||||||
const { token, isMfaEnabled } = await selectOrganization({ organizationId });
|
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({ organizationId });
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
|
if (mfaMethod) {
|
||||||
|
setRequiredMfaMethod(mfaMethod);
|
||||||
|
}
|
||||||
toggleShowMfa.on();
|
toggleShowMfa.on();
|
||||||
setMfaSuccessCallback(() => finishWithOrgWorkflow);
|
setMfaSuccessCallback(() => finishWithOrgWorkflow);
|
||||||
return;
|
return;
|
||||||
@@ -167,10 +172,15 @@ export const PasswordStep = ({ providerAuthToken, email, password, setPassword }
|
|||||||
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
// case: organization ID is present from the provider auth token -- select the org and use the new jwt token in the CLI, then navigate to the org
|
||||||
if (organizationId) {
|
if (organizationId) {
|
||||||
const finishWithOrgWorkflow = async () => {
|
const finishWithOrgWorkflow = async () => {
|
||||||
const { token, isMfaEnabled } = await selectOrganization({ organizationId });
|
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({
|
||||||
|
organizationId
|
||||||
|
});
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
|
if (mfaMethod) {
|
||||||
|
setRequiredMfaMethod(mfaMethod);
|
||||||
|
}
|
||||||
toggleShowMfa.on();
|
toggleShowMfa.on();
|
||||||
setMfaSuccessCallback(() => finishWithOrgWorkflow);
|
setMfaSuccessCallback(() => finishWithOrgWorkflow);
|
||||||
return;
|
return;
|
||||||
@@ -283,6 +293,7 @@ export const PasswordStep = ({ providerAuthToken, email, password, setPassword }
|
|||||||
<Mfa
|
<Mfa
|
||||||
email={email}
|
email={email}
|
||||||
successCallback={mfaSuccessCallback}
|
successCallback={mfaSuccessCallback}
|
||||||
|
method={requiredMfaMethod}
|
||||||
closeMfa={() => toggleShowMfa.off()}
|
closeMfa={() => toggleShowMfa.off()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+44
-1
@@ -1,6 +1,6 @@
|
|||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import { Switch, UpgradePlanModal } from "@app/components/v2";
|
import { FormControl, Select, SelectItem, Switch, UpgradePlanModal } from "@app/components/v2";
|
||||||
import {
|
import {
|
||||||
OrgPermissionActions,
|
OrgPermissionActions,
|
||||||
OrgPermissionSubjects,
|
OrgPermissionSubjects,
|
||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
useSubscription
|
useSubscription
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import { useUpdateOrg } from "@app/hooks/api";
|
import { useUpdateOrg } from "@app/hooks/api";
|
||||||
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
export const OrgGenericAuthSection = () => {
|
export const OrgGenericAuthSection = () => {
|
||||||
@@ -43,6 +44,32 @@ export const OrgGenericAuthSection = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUpdateSelectedMfa = async (selectedMfaMethod: MfaMethod) => {
|
||||||
|
try {
|
||||||
|
if (!currentOrg?.id) return;
|
||||||
|
if (!subscription?.enforceMfa) {
|
||||||
|
handlePopUpOpen("upgradePlan");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await mutateAsync({
|
||||||
|
orgId: currentOrg?.id,
|
||||||
|
selectedMfaMethod
|
||||||
|
});
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully updated preferred MFA method",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
createNotification({
|
||||||
|
text: (err as { response: { data: { message: string } } }).response.data.message,
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
<div className="mb-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
@@ -62,6 +89,22 @@ export const OrgGenericAuthSection = () => {
|
|||||||
<p className="text-sm text-mineshaft-300">
|
<p className="text-sm text-mineshaft-300">
|
||||||
Enforce members to authenticate with MFA in order to access the organization
|
Enforce members to authenticate with MFA in order to access the organization
|
||||||
</p>
|
</p>
|
||||||
|
{currentOrg?.enforceMfa && (
|
||||||
|
<FormControl label="Preferred 2FA method" className="mt-3">
|
||||||
|
<Select
|
||||||
|
className="min-w-[20rem] border border-mineshaft-500"
|
||||||
|
onValueChange={handleUpdateSelectedMfa}
|
||||||
|
defaultValue={currentOrg.selectedMfaMethod ?? MfaMethod.EMAIL}
|
||||||
|
>
|
||||||
|
<SelectItem value={MfaMethod.EMAIL} key="mfa-method-email">
|
||||||
|
Email
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={MfaMethod.TOTP} key="mfa-method-totp">
|
||||||
|
Mobile Authenticator
|
||||||
|
</SelectItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export const MFASection = () => {
|
|||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{shouldShowRecoveryCodes && totpConfiguration.recoveryCodes.length && (
|
{shouldShowRecoveryCodes && totpConfiguration.recoveryCodes && (
|
||||||
<div className="mt-4 bg-mineshaft-600 p-4">
|
<div className="mt-4 bg-mineshaft-600 p-4">
|
||||||
{totpConfiguration.recoveryCodes.map((code) => (
|
{totpConfiguration.recoveryCodes.map((code) => (
|
||||||
<div key={code}>{code}</div>
|
<div key={code}>{code}</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import SecurityClient from "@app/components/utilities/SecurityClient";
|
|||||||
import { Button, Input } from "@app/components/v2";
|
import { Button, Input } from "@app/components/v2";
|
||||||
import { useToggle } from "@app/hooks";
|
import { useToggle } from "@app/hooks";
|
||||||
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
||||||
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
import ProjectService from "@app/services/ProjectService";
|
import ProjectService from "@app/services/ProjectService";
|
||||||
import { Mfa } from "@app/views/Login/Mfa";
|
import { Mfa } from "@app/views/Login/Mfa";
|
||||||
@@ -57,6 +58,7 @@ export const UserInfoSSOStep = ({
|
|||||||
const [organizationNameError, setOrganizationNameError] = useState(false);
|
const [organizationNameError, setOrganizationNameError] = useState(false);
|
||||||
const [attributionSource, setAttributionSource] = useState("");
|
const [attributionSource, setAttributionSource] = useState("");
|
||||||
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
const [shouldShowMfa, toggleShowMfa] = useToggle(false);
|
||||||
|
const [requiredMfaMethod, setRequiredMfaMethod] = useState(MfaMethod.EMAIL);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
||||||
@@ -178,12 +180,15 @@ export const UserInfoSSOStep = ({
|
|||||||
|
|
||||||
const completeSignupFlow = async () => {
|
const completeSignupFlow = async () => {
|
||||||
try {
|
try {
|
||||||
const { isMfaEnabled, token } = await selectOrganization({
|
const { isMfaEnabled, token, mfaMethod } = await selectOrganization({
|
||||||
organizationId: orgId
|
organizationId: orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
|
if (mfaMethod) {
|
||||||
|
setRequiredMfaMethod(mfaMethod);
|
||||||
|
}
|
||||||
toggleShowMfa.on();
|
toggleShowMfa.on();
|
||||||
setMfaSuccessCallback(() => completeSignupFlow);
|
setMfaSuccessCallback(() => completeSignupFlow);
|
||||||
return;
|
return;
|
||||||
@@ -231,6 +236,7 @@ export const UserInfoSSOStep = ({
|
|||||||
hideLogo
|
hideLogo
|
||||||
email={username}
|
email={username}
|
||||||
successCallback={mfaSuccessCallback}
|
successCallback={mfaSuccessCallback}
|
||||||
|
method={requiredMfaMethod}
|
||||||
closeMfa={() => toggleShowMfa.off()}
|
closeMfa={() => toggleShowMfa.off()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user