diff --git a/cmd/server/assets/login/login.html b/cmd/server/assets/login/login.html index 94ea2f813..2e367cc72 100644 --- a/cmd/server/assets/login/login.html +++ b/cmd/server/assets/login/login.html @@ -138,6 +138,10 @@ flash.clear(); flash.error('Unsupported 2nd factor authentication type.'); } + } else if (error.code == 'auth/too-many-requests'){ + flash.clear(); + flash.error(err.message); + $submit.prop('disabled', false); } else { flash.clear(); flash.error("Sign-in failed. Please try again."); diff --git a/internal/firebase/error.go b/internal/firebase/error.go index b12495ffc..dcc4a425c 100644 --- a/internal/firebase/error.go +++ b/internal/firebase/error.go @@ -25,6 +25,7 @@ var ( ErrCredentialTooOld = &ErrorDetails{Err: "CREDENTIAL_TOO_OLD_LOGIN_AGAIN"} ErrTokenExpired = &ErrorDetails{Err: "TOKEN_EXPIRED"} ErrInvalidToken = &ErrorDetails{Err: "INVALID_ID_TOKEN"} + ErrTooManyAttempts = &ErrorDetails{Err: "TOO_MANY_ATTEMPTS_TRY_LATER"} ) var _ error = (*ErrorDetails)(nil) diff --git a/pkg/controller/login/reset_password.go b/pkg/controller/login/reset_password.go index 9055eae98..c286435dc 100644 --- a/pkg/controller/login/reset_password.go +++ b/pkg/controller/login/reset_password.go @@ -57,6 +57,12 @@ func (c *Controller) HandleSubmitResetPassword() http.Handler { } if err := c.firebaseInternal.SendPasswordResetEmail(ctx, strings.TrimSpace(form.Email)); err != nil { + if errors.Is(err, firebase.ErrTooManyAttempts) { + flash.Error("Too many attempts have been made. Please wait and try again later.") + c.renderResetPassword(ctx, w, flash) + return + } + // Treat not-found like success so we don't leak details. if !errors.Is(err, firebase.ErrEmailNotFound) { flash.Error("Password reset failed.")