diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json
index 5e8756c89b..db46321b05 100644
--- a/apps/login/locales/de.json
+++ b/apps/login/locales/de.json
@@ -71,7 +71,8 @@
},
"set": {
"title": "2-Faktor einrichten",
- "description": "Wählen Sie einen der folgenden zweiten Faktoren."
+ "description": "Wählen Sie einen der folgenden zweiten Faktoren.",
+ "skip": "Überspringen"
}
},
"otp": {
diff --git a/apps/login/locales/en.json b/apps/login/locales/en.json
index 3101f222d5..36776ccbd9 100644
--- a/apps/login/locales/en.json
+++ b/apps/login/locales/en.json
@@ -71,7 +71,8 @@
},
"set": {
"title": "Set up 2-Factor",
- "description": "Choose one of the following second factors."
+ "description": "Choose one of the following second factors.",
+ "skip": "Skip"
}
},
"otp": {
diff --git a/apps/login/locales/es.json b/apps/login/locales/es.json
index 5a9b6f6324..4eba3a9696 100644
--- a/apps/login/locales/es.json
+++ b/apps/login/locales/es.json
@@ -71,7 +71,8 @@
},
"set": {
"title": "Configurar autenticación de 2 factores",
- "description": "Elige uno de los siguientes factores secundarios."
+ "description": "Elige uno de los siguientes factores secundarios.",
+ "skip": "Omitir"
}
},
"otp": {
diff --git a/apps/login/locales/it.json b/apps/login/locales/it.json
index 1423c43cfe..d0969c86b3 100644
--- a/apps/login/locales/it.json
+++ b/apps/login/locales/it.json
@@ -71,7 +71,8 @@
},
"set": {
"title": "Configura l'autenticazione a 2 fattori",
- "description": "Scegli uno dei seguenti secondi fattori."
+ "description": "Scegli uno dei seguenti secondi fattori.",
+ "skip": "Salta"
}
},
"otp": {
diff --git a/apps/login/locales/zh.json b/apps/login/locales/zh.json
index acd03cc5b6..9c87a53a65 100644
--- a/apps/login/locales/zh.json
+++ b/apps/login/locales/zh.json
@@ -71,7 +71,8 @@
},
"set": {
"title": "设置双因素认证",
- "description": "选择以下的一个第二因素。"
+ "description": "选择以下的一个第二因素。",
+ "skip": "跳过"
}
},
"otp": {
diff --git a/apps/login/src/app/(login)/mfa/set/page.tsx b/apps/login/src/app/(login)/mfa/set/page.tsx
index a885a36c7a..a8f16f23f2 100644
--- a/apps/login/src/app/(login)/mfa/set/page.tsx
+++ b/apps/login/src/app/(login)/mfa/set/page.tsx
@@ -161,6 +161,12 @@ export default async function Page(props: {
>
)}
+ {force !== "true" && (
+
+ )}
+
diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts
index 98c34a3de6..6fd3f67bcd 100644
--- a/apps/login/src/lib/server/password.ts
+++ b/apps/login/src/lib/server/password.ts
@@ -16,7 +16,7 @@ import {
setPassword,
setUserPassword,
} from "@/lib/zitadel";
-import { create } from "@zitadel/client";
+import { ConnectError, create } from "@zitadel/client";
import { createServerTransport } from "@zitadel/client/node";
import { createUserServiceClient } from "@zitadel/client/v2";
import {
@@ -267,7 +267,8 @@ export async function sendPassword(command: UpdateSessionCommand) {
return { error: "Could not verify password!" };
}
- const mfaFactorCheck = checkMFAFactors(
+ const mfaFactorCheck = await checkMFAFactors(
+ serviceUrl,
session,
loginSettings,
authMethods,
@@ -433,7 +434,7 @@ export async function checkSessionAndSetPassword({
},
{},
)
- .catch((error) => {
+ .catch((error: ConnectError) => {
console.log(error);
if (error.code === 7) {
return { error: "Session is not valid." };
diff --git a/apps/login/src/lib/server/verify.ts b/apps/login/src/lib/server/verify.ts
index 38bddb9428..4de697e772 100644
--- a/apps/login/src/lib/server/verify.ts
+++ b/apps/login/src/lib/server/verify.ts
@@ -203,7 +203,8 @@ export async function sendVerification(command: VerifyUserByEmailCommand) {
}
// redirect to mfa factor if user has one, or redirect to set one up
- const mfaFactorCheck = checkMFAFactors(
+ const mfaFactorCheck = await checkMFAFactors(
+ serviceUrl,
session,
loginSettings,
authMethodResponse.authMethodTypes,
@@ -407,12 +408,12 @@ export async function sendVerificationRedirectWithoutCheck(
const loginSettings = await getLoginSettings({
serviceUrl,
-
organization: user.details?.resourceOwner,
});
// redirect to mfa factor if user has one, or redirect to set one up
- const mfaFactorCheck = checkMFAFactors(
+ const mfaFactorCheck = await checkMFAFactors(
+ serviceUrl,
session,
loginSettings,
authMethodResponse.authMethodTypes,
diff --git a/apps/login/src/lib/verify-helper.ts b/apps/login/src/lib/verify-helper.ts
index e8afef6890..fcc46e175c 100644
--- a/apps/login/src/lib/verify-helper.ts
+++ b/apps/login/src/lib/verify-helper.ts
@@ -5,6 +5,7 @@ import { PasswordExpirySettings } from "@zitadel/proto/zitadel/settings/v2/passw
import { HumanUser } from "@zitadel/proto/zitadel/user/v2/user_pb";
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import moment from "moment";
+import { getUserByID } from "./zitadel";
export function checkPasswordChangeRequired(
expirySettings: PasswordExpirySettings | undefined,
@@ -100,7 +101,8 @@ export function checkEmailVerification(
}
}
-export function checkMFAFactors(
+export async function checkMFAFactors(
+ serviceUrl: string,
session: Session,
loginSettings: LoginSettings | undefined,
authMethods: AuthenticationMethodType[],
@@ -188,31 +190,42 @@ export function checkMFAFactors(
);
}
+ // TODO: provide a way to setup passkeys on mfa page?
+ return { redirect: `/mfa/set?` + params };
+ } else if (
+ loginSettings?.mfaInitSkipLifetime &&
+ (loginSettings.mfaInitSkipLifetime.nanos > 0 ||
+ loginSettings.mfaInitSkipLifetime.seconds > 0) &&
+ !availableMultiFactors.length &&
+ session?.factors?.user?.id
+ ) {
+ const user = await getUserByID({
+ serviceUrl,
+ userId: session.factors?.user?.id,
+ });
+ if (
+ user.user?.type?.case === "human" &&
+ user.user?.type?.value.mfaInitSkipped
+ ) {
+ }
+ const params = new URLSearchParams({
+ loginName: session.factors?.user?.loginName as string,
+ force: "false", // this defines if the mfa is not forced in the settings and can be skipped
+ checkAfter: "true", // this defines if the check is directly made after the setup
+ });
+
+ if (requestId) {
+ params.append("requestId", requestId);
+ }
+
+ if (organization || session.factors?.user?.organizationId) {
+ params.append(
+ "organization",
+ organization ?? (session.factors?.user?.organizationId as string),
+ );
+ }
+
// TODO: provide a way to setup passkeys on mfa page?
return { redirect: `/mfa/set?` + params };
}
-
- // TODO: implement passkey setup
-
- // else if (
- // submitted.factors &&
- // !submitted.factors.webAuthN && // if session was not verified with a passkey
- // promptPasswordless && // if explicitly prompted due policy
- // !isAlternative // escaped if password was used as an alternative method
- // ) {
- // const params = new URLSearchParams({
- // loginName: submitted.factors.user.loginName,
- // prompt: "true",
- // });
-
- // if (requestId) {
- // params.append("requestId", requestId);
- // }
-
- // if (organization) {
- // params.append("organization", organization);
- // }
-
- // return router.push(`/passkey/set?` + params);
- // }
}