fix: reset password email enumeration

This commit is contained in:
Piyush Gupta
2025-06-30 18:30:07 +05:30
parent 3f98283d4d
commit 49560ccba8
5 changed files with 32 additions and 21 deletions

View File

@@ -19,7 +19,6 @@ import { Label } from "@/modules/ui/components/label";
import { zodResolver } from "@hookform/resolvers/zod";
import { useTranslate } from "@tolgee/react";
import { ChevronDownIcon } from "lucide-react";
import { signOut } from "next-auth/react";
import { useState } from "react";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import toast from "react-hot-toast";
@@ -135,15 +134,15 @@ export const EditProfileDetailsForm = ({
setIsResettingPassword(true);
const resetPasswordResponse = await forgotPasswordAction({ email: user.email });
await forgotPasswordAction({ email: user.email });
if (!resetPasswordResponse?.data) {
const errorMessage = getFormattedErrorMessage(resetPasswordResponse);
toast.error(errorMessage);
} else {
toast.success(t("auth.forgot-password.email-sent.heading"));
await signOut({ callbackUrl: "/auth/login" });
}
toast.success(t("auth.forgot-password.email-sent.heading"));
await signOutWithAudit({
reason: "password_reset",
redirectUrl: "/auth/login",
redirect: true,
callbackUrl: "/auth/login",
});
setIsResettingPassword(false);
};

View File

@@ -13,7 +13,13 @@ export const logSignOutAction = async (
userId: string,
userEmail: string,
context: {
reason?: "user_initiated" | "account_deletion" | "email_change" | "session_timeout" | "forced_logout";
reason?:
| "user_initiated"
| "account_deletion"
| "email_change"
| "session_timeout"
| "forced_logout"
| "password_reset";
redirectUrl?: string;
organizationId?: string;
}

View File

@@ -5,7 +5,7 @@ import { actionClient } from "@/lib/utils/action-client";
import { getUserByEmail } from "@/modules/auth/lib/user";
import { sendForgotPasswordEmail } from "@/modules/email";
import { z } from "zod";
import { OperationNotAllowedError, ResourceNotFoundError } from "@formbricks/types/errors";
import { OperationNotAllowedError } from "@formbricks/types/errors";
import { ZUserEmail } from "@formbricks/types/user";
const ZForgotPasswordAction = z.object({
@@ -21,15 +21,9 @@ export const forgotPasswordAction = actionClient
const user = await getUserByEmail(parsedInput.email);
if (!user) {
throw new ResourceNotFoundError("user", parsedInput.email);
}
if (user.identityProvider !== "email") {
throw new OperationNotAllowedError("Password reset is not allowed for SSO users");
if (!user || user.identityProvider !== "email") {
return;
}
await sendForgotPasswordEmail(user);
return { success: true };
});

View File

@@ -3,7 +3,13 @@ import { signOut } from "next-auth/react";
import { logger } from "@formbricks/logger";
interface UseSignOutOptions {
reason?: "user_initiated" | "account_deletion" | "email_change" | "session_timeout" | "forced_logout";
reason?:
| "user_initiated"
| "account_deletion"
| "email_change"
| "session_timeout"
| "forced_logout"
| "password_reset";
redirectUrl?: string;
organizationId?: string;
redirect?: boolean;

View File

@@ -283,7 +283,13 @@ export const logSignOut = (
userId: string,
userEmail: string,
context?: {
reason?: "user_initiated" | "account_deletion" | "email_change" | "session_timeout" | "forced_logout";
reason?:
| "user_initiated"
| "account_deletion"
| "email_change"
| "session_timeout"
| "forced_logout"
| "password_reset";
redirectUrl?: string;
organizationId?: string;
}