EmailOtp's forget password user enumeration #3972
-
|
Hi all! I'm using email otp plugin for forget password and when i use an non existent email i will get a error config: import { betterAuth } from "better-auth";
import { APIError } from "better-auth/api";
import { expo } from "@better-auth/expo";
import { admin, createAuthMiddleware, emailOTP } from "better-auth/plugins";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/src/db";
import { registerSchema } from "./schemas/auth";
export const auth = betterAuth({
emailAndPassword: {
enabled: true, // Enable authentication using email and password.
},
hooks: {
before: createAuthMiddleware(async (ctx) => {
if (ctx.path === "/sign-up/email") {
if (ctx.body) {
const result = registerSchema.safeParse(ctx.body);
if (!result.success) {
const errorMessage = result.error.issues[0].message;
throw new APIError("BAD_REQUEST", {
message: errorMessage,
});
}
}
}
}),
},
trustedOrigins: ["bevy://"],
database: drizzleAdapter(db, {
provider: "pg", // or "pg" or "mysql"
}),
plugins: [
emailOTP({
// disableSignUp: true,
overrideDefaultEmailVerification: true,
async sendVerificationOTP({ email, otp, type }) {
console.log("=== EMAIL OTP SEND TRIGGERED ===");
console.log("Email:", email);
console.log("OTP:", otp);
console.log("Type:", type);
console.log("Timestamp:", new Date().toISOString());
if (type === "sign-in") {
console.log("📧 Sending OTP for sign-in");
// Send the OTP for sign-in
console.log("Sign-in OTP email would be sent to:", email);
} else if (type === "email-verification") {
console.log("✅ Sending OTP for email verification");
// Send the OTP for email verification
console.log("Email verification OTP would be sent to:", email);
} else {
console.log("🔐 Sending OTP for password reset");
// Send the OTP for password reset
console.log("Password reset OTP would be sent to:", email);
}
console.log("=== EMAIL OTP SEND COMPLETED ===\n");
},
}),
expo(),
admin(),
],
}); |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 5 replies
-
|
Hi @chanithecat! I'm Dosu and I’m helping the better-auth team. You're right—returning a To match this behavior in your forgot password flow, you should use the sendVerificationOTP endpoint for password resets, or adapt your flow so that when a non-existent email is submitted, you always return a generic success response (and never reveal whether the email exists). If you need to override the default endpoint, you can use a custom middleware or hook to intercept the error and replace it with a generic success response. This approach aligns with how token mode email verification works, where errors are always generic and never reveal user existence (source). If you want a code example or guidance on how to override the endpoint or add a hook, let me know! To reply, just mention @dosu. Docs are dead. Just use Dosu. |
Beta Was this translation helpful? Give feedback.
-
|
im down to submit a pr is a flag like |
Beta Was this translation helpful? Give feedback.
-
|
@dosubot i tried to patch the otp plugin to do the same thing when using i also added the |
Beta Was this translation helpful? Give feedback.
@dosubot i tried to patch the otp plugin to do the same thing when using
requestPasswordResetendpoint that returns a 200 but uses the logger to print2025-08-13T16:22:02.249Z ERROR [Better Auth]: Reset Password: User not found { email: "john.doe@example.com", }but when i hit the/forget-password/email-otpit returns a 200 but does not log like therequestPasswordReset. any idea why?i also added the
maskusernotfoundonforgetpasswordand set it to false by default.