diff --git a/apps/login/app/(login)/mfa/set/page.tsx b/apps/login/app/(login)/mfa/set/page.tsx
index 1625e9bb62f..f8549780432 100644
--- a/apps/login/app/(login)/mfa/set/page.tsx
+++ b/apps/login/app/(login)/mfa/set/page.tsx
@@ -14,6 +14,7 @@ import {
getMostRecentCookieWithLoginname,
getSessionCookieById,
} from "#/utils/cookies";
+import { user } from "@zitadel/server";
export default async function Page({
searchParams,
@@ -23,7 +24,7 @@ export default async function Page({
const { loginName, checkAfter, authRequestId, organization, sessionId } =
searchParams;
- const sessionFactors = sessionId
+ const sessionWithData = sessionId
? await loadSessionById(sessionId, organization)
: await loadSessionByLoginname(loginName, organization);
@@ -37,13 +38,16 @@ export default async function Page({
);
return getSession(server, recent.id, recent.token).then((response) => {
if (response?.session && response.session.factors?.user?.id) {
- return listAuthenticationMethodTypes(
- response.session.factors.user.id
- ).then((methods) => {
- return {
- factors: response.session?.factors,
- authMethods: methods.authMethodTypes ?? [],
- };
+ const userId = response.session.factors.user.id;
+ return listAuthenticationMethodTypes(userId).then((methods) => {
+ return getUserByID(userId).then((user) => {
+ return {
+ factors: response.session?.factors,
+ authMethods: methods.authMethodTypes ?? [],
+ phoneVerified: user.user?.human?.phone?.isVerified ?? false,
+ emailVerified: user.user?.human?.email?.isVerified ?? false,
+ };
+ });
});
}
});
@@ -53,13 +57,16 @@ export default async function Page({
const recent = await getSessionCookieById(sessionId, organization);
return getSession(server, recent.id, recent.token).then((response) => {
if (response?.session && response.session.factors?.user?.id) {
- return listAuthenticationMethodTypes(
- response.session.factors.user.id
- ).then((methods) => {
- return {
- factors: response.session?.factors,
- authMethods: methods.authMethodTypes ?? [],
- };
+ const userId = response.session.factors.user.id;
+ return listAuthenticationMethodTypes(userId).then((methods) => {
+ return getUserByID(userId).then((user) => {
+ return {
+ factors: response.session?.factors,
+ authMethods: methods.authMethodTypes ?? [],
+ phoneVerified: user.user?.human?.phone?.isVerified ?? false,
+ emailVerified: user.user?.human?.email?.isVerified ?? false,
+ };
+ });
});
}
});
@@ -75,10 +82,10 @@ export default async function Page({
Choose one of the following second factors.
- {sessionFactors && (
+ {sessionWithData && (
@@ -88,14 +95,16 @@ export default async function Page({
Provide your active session as loginName param
)}
- {loginSettings && sessionFactors ? (
+ {loginSettings && sessionWithData ? (
) : (
diff --git a/apps/login/ui/AuthMethods.tsx b/apps/login/ui/AuthMethods.tsx
index b9748a3ef98..aa204a23ed1 100644
--- a/apps/login/ui/AuthMethods.tsx
+++ b/apps/login/ui/AuthMethods.tsx
@@ -2,16 +2,37 @@ import clsx from "clsx";
import Link from "next/link";
import { BadgeState, StateBadge } from "./StateBadge";
import { CheckIcon } from "@heroicons/react/24/solid";
+import { ReactNode } from "react";
const cardClasses = (alreadyAdded: boolean) =>
clsx(
"relative bg-background-light-400 dark:bg-background-dark-400 group block space-y-1.5 rounded-md px-5 py-3 border border-divider-light dark:border-divider-dark transition-all ",
- alreadyAdded ? "" : "hover:shadow-lg hover:dark:bg-white/10"
+ alreadyAdded
+ ? "opacity-50 cursor-default"
+ : "hover:shadow-lg hover:dark:bg-white/10"
);
+const LinkWrapper = ({
+ alreadyAdded,
+ children,
+ link,
+}: {
+ alreadyAdded: boolean;
+ children: ReactNode;
+ link: string;
+}) => {
+ return !alreadyAdded ? (
+
+ {children}
+
+ ) : (
+ {children}
+ );
+};
+
export const TOTP = (alreadyAdded: boolean, link: string) => {
return (
-
+
>
)}
-
+
);
};
export const U2F = (alreadyAdded: boolean, link: string) => {
return (
-
+
{
>
)}
-
+
);
};
export const EMAIL = (alreadyAdded: boolean, link: string) => {
return (
-
+
{
>
)}
-
+
);
};
export const SMS = (alreadyAdded: boolean, link: string) => {
return (
-
+
{
>
)}
-
+
);
};
diff --git a/apps/login/ui/ChooseSecondFactorToSetup.tsx b/apps/login/ui/ChooseSecondFactorToSetup.tsx
index 6e13c5014ae..6f5d34512e6 100644
--- a/apps/login/ui/ChooseSecondFactorToSetup.tsx
+++ b/apps/login/ui/ChooseSecondFactorToSetup.tsx
@@ -11,6 +11,8 @@ type Props = {
loginSettings: LoginSettings;
userMethods: AuthenticationMethodType[];
checkAfter: boolean;
+ phoneVerified: boolean;
+ emailVerified: boolean;
};
export default function ChooseSecondFactorToSetup({
@@ -21,6 +23,8 @@ export default function ChooseSecondFactorToSetup({
loginSettings,
userMethods,
checkAfter,
+ phoneVerified,
+ emailVerified,
}: Props) {
const params = new URLSearchParams({});
@@ -43,20 +47,15 @@ export default function ChooseSecondFactorToSetup({
return (
{loginSettings.secondFactors.map((factor, i) => {
- return (
-
- {factor === 1 &&
- TOTP(
- userMethods.includes(4),
- userMethods.includes(4) ? "" : "/otp/time-based/set?" + params
- )}
- {factor === 2 && U2F(userMethods.includes(5), "/u2f/set?" + params)}
- {factor === 3 &&
- EMAIL(userMethods.includes(7), "/otp/email/set?" + params)}
- {factor === 4 &&
- SMS(userMethods.includes(6), "/otp/sms/set?" + params)}
-
- );
+ return factor === 1
+ ? TOTP(userMethods.includes(4), "/otp/time-based/set?" + params)
+ : factor === 2
+ ? U2F(userMethods.includes(5), "/u2f/set?" + params)
+ : factor === 3 && emailVerified
+ ? EMAIL(userMethods.includes(7), "/otp/email/set?" + params)
+ : factor === 4 && phoneVerified
+ ? SMS(userMethods.includes(6), "/otp/sms/set?" + params)
+ : null;
})}
);