revert mfa check on password change

This commit is contained in:
Max Peintner
2025-05-23 14:09:18 +02:00
parent dffa94878e
commit e304760240

View File

@@ -13,6 +13,7 @@ import {
listAuthenticationMethodTypes,
listUsers,
passwordReset,
setPassword,
setUserPassword,
} from "@/lib/zitadel";
import { ConnectError, create } from "@zitadel/client";
@@ -24,7 +25,10 @@ import {
} from "@zitadel/proto/zitadel/session/v2/session_service_pb";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { User, UserState } from "@zitadel/proto/zitadel/user/v2/user_pb";
import { SetPasswordRequestSchema } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import {
AuthenticationMethodType,
SetPasswordRequestSchema,
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { headers } from "next/headers";
import { getNextUrl } from "../client";
import { getSessionCookieById, getSessionCookieByLoginName } from "../cookies";
@@ -392,32 +396,67 @@ export async function checkSessionAndSetPassword({
return { error: "Could not load auth methods" };
}
const transport = async (serviceUrl: string, token: string) => {
return createServerTransport(token, {
baseUrl: serviceUrl,
});
};
const requiredAuthMethodsForForceMFA = [
AuthenticationMethodType.OTP_EMAIL,
AuthenticationMethodType.OTP_SMS,
AuthenticationMethodType.TOTP,
AuthenticationMethodType.U2F,
];
const myUserService = async (serviceUrl: string, sessionToken: string) => {
const transportPromise = await transport(serviceUrl, sessionToken);
return createUserServiceClient(transportPromise);
};
const hasNoMFAMethods = requiredAuthMethodsForForceMFA.every(
(method) => !authmethods.authMethodTypes.includes(method),
);
const selfService = await myUserService(serviceUrl, `${sessionCookie.token}`);
const loginSettings = await getLoginSettings({
serviceUrl,
organization: session.factors.user.organizationId,
});
return selfService
.setPassword(
{
userId: session.factors.user.id,
newPassword: { password, changeRequired: false },
},
{},
)
.catch((error: ConnectError) => {
console.log(error);
if (error.code === 7) {
return { error: "Session is not valid." };
const forceMfa = !!(
loginSettings?.forceMfa || loginSettings?.forceMfaLocalOnly
);
// if the user has no MFA but MFA is enforced, we can set a password otherwise we use the token of the user
if (forceMfa && hasNoMFAMethods) {
return setPassword({ serviceUrl, payload }).catch((error) => {
// throw error if failed precondition (ex. User is not yet initialized)
if (error.code === 9 && error.message) {
return { error: "Failed precondition" };
} else {
throw error;
}
throw error;
});
} else {
const transport = async (serviceUrl: string, token: string) => {
return createServerTransport(token, {
baseUrl: serviceUrl,
});
};
const myUserService = async (serviceUrl: string, sessionToken: string) => {
const transportPromise = await transport(serviceUrl, sessionToken);
return createUserServiceClient(transportPromise);
};
const selfService = await myUserService(
serviceUrl,
`${sessionCookie.token}`,
);
return selfService
.setPassword(
{
userId: session.factors.user.id,
newPassword: { password, changeRequired: false },
},
{},
)
.catch((error: ConnectError) => {
console.log(error);
if (error.code === 7) {
return { error: "Session is not valid." };
}
throw error;
});
}
}