diff --git a/internal/api/magic_link.go b/internal/api/magic_link.go index 2393059de..5994bfb0b 100644 --- a/internal/api/magic_link.go +++ b/internal/api/magic_link.go @@ -83,8 +83,10 @@ func (a *API) MagicLink(w http.ResponseWriter, r *http.Request) error { } if isNewUser { // User either doesn't exist or hasn't completed the signup process. - // Sign them up with temporary password. - password := crypto.GeneratePassword(config.Password.RequiredCharacters, 33) + // Sign them up with temporary password that satisfies the configured + // minimum password length, clamped to the bcrypt limit. + passwordLen := min(max(33, config.Password.MinLength), MaxPasswordLength) + password := crypto.GeneratePassword(config.Password.RequiredCharacters, passwordLen) signUpParams := &SignupParams{ Email: params.Email, diff --git a/internal/api/otp.go b/internal/api/otp.go index 5f12b0bbe..f88e2e29c 100644 --- a/internal/api/otp.go +++ b/internal/api/otp.go @@ -138,8 +138,10 @@ func (a *API) SmsOtp(w http.ResponseWriter, r *http.Request) error { } if isNewUser { // User either doesn't exist or hasn't completed the signup process. - // Sign them up with temporary password. - password, err := password.Generate(64, 10, 1, false, true) + // Sign them up with temporary password that satisfies the configured + // minimum password length, clamped to the bcrypt limit. + passwordLen := min(max(64, config.Password.MinLength), MaxPasswordLength) + password, err := password.Generate(passwordLen, 10, 1, false, true) if err != nil { return apierrors.NewInternalServerError("error creating user").WithInternalError(err) } diff --git a/internal/api/otp_test.go b/internal/api/otp_test.go index 7a99f3d9c..813c0c929 100644 --- a/internal/api/otp_test.go +++ b/internal/api/otp_test.go @@ -262,6 +262,28 @@ func (ts *OtpTestSuite) TestNoSignupsForOtp() { }) } +func (ts *OtpTestSuite) TestOtpRespectsMinPasswordLength() { + // Regression test for https://github.com/supabase/auth/issues/2456. + // OTP signup internally generates a temporary password that must satisfy + // the configured minimum password length, otherwise the signup call fails + // with a 422 WeakPasswordError even though the caller never supplied a + // password. + ts.Config.Password.MinLength = 40 + + var buffer bytes.Buffer + require.NoError(ts.T(), json.NewEncoder(&buffer).Encode(map[string]interface{}{ + "email": "min-length@example.com", + })) + + req := httptest.NewRequest(http.MethodPost, "/otp", &buffer) + req.Header.Set("Content-Type", "application/json") + + w := httptest.NewRecorder() + ts.API.handler.ServeHTTP(w, req) + + require.Equal(ts.T(), http.StatusOK, w.Code) +} + func (ts *OtpTestSuite) TestSubsequentOtp() { ts.Config.SMTP.MaxFrequency = 0 userEmail := "foo@example.com"