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; })}
);