fix(auth): gate email-otp auto-signup behind DISABLE_EMAIL_SIGNUP (#5840)

* fix(auth): gate email-otp auto-signup behind DISABLE_EMAIL_SIGNUP

* fix(auth): also close otp auto-signup under DISABLE_REGISTRATION
This commit is contained in:
Waleed
2026-07-21 23:26:44 -07:00
committed by GitHub
parent 93fbf584a2
commit 1410aae3e3
+17 -5
View File
@@ -768,6 +768,13 @@ export const auth = betterAuth({
},
emailAndPassword: {
enabled: true,
/**
* Same flag that hides the email/password signup form (DISABLE_EMAIL_SIGNUP).
* Blocks /sign-up/email at the better-auth layer so ripping out the frontend
* form cannot be bypassed by calling the endpoint directly. Existing users
* can still sign in.
*/
disableSignUp: isEmailSignupDisabled,
requireEmailVerification: isEmailVerificationEnabled,
/**
* When someone signs up with an already-registered email, better-auth returns a
@@ -891,11 +898,6 @@ export const auth = betterAuth({
})
}
if (isEmailSignupDisabled && ctx.path.startsWith('/sign-up/email'))
throw new APIError('FORBIDDEN', {
message: 'Email sign-up is disabled. Please use Google, Microsoft, or GitHub.',
})
const isSignIn = ctx.path.startsWith('/sign-in')
const isSignUp = ctx.path.startsWith('/sign-up')
@@ -1039,6 +1041,16 @@ export const auth = betterAuth({
throw error
}
},
/**
* Without this, /sign-in/email-otp auto-registers any unknown email —
* bypassing the signup gate entirely (no captcha, no /sign-up path).
* Gated by the same DISABLE_EMAIL_SIGNUP flag as the signup form (and by
* DISABLE_REGISTRATION, whose /sign-up path check has the same blind
* spot); when set, better-auth also silently skips sending OTPs to
* unknown emails (enumeration-safe) while existing users keep OTP
* sign-in.
*/
disableSignUp: isEmailSignupDisabled || isRegistrationDisabled,
sendVerificationOnSignUp: false,
otpLength: 6, // Explicitly set the OTP length
expiresIn: 15 * 60, // 15 minutes in seconds