At first I used Rachel's answer, but because the error is still attached to form field the end user can tell if they have a valid email and an incorrect password... So, as I use flash messages for pretty much all feedback, I found editing flask_security itself was the easiest approach for me.
If you open the file
site-packages\flask_security\forms.py
you'll find the following code:
if self.user is None:
self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
return False
if not self.user.password:
self.password.errors.append(get_message('PASSWORD_NOT_SET')[0])
return False
if not verify_and_update_password(self.password.data, self.user):
self.password.errors.append(get_message('INVALID_PASSWORD')[0])
return False
if requires_confirmation(self.user):
self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
return False
if not self.user.is_active:
self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
return False
You can see that it appends an error the relevant field (email or password), You could comment those out to simply provide no feedback on failure - personally I flashed an error as below:
if self.user is None:
#self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
flash('Error: There was an issue logging you in')
return False
if not self.user.password:
#self.password.errors.append(get_message('PASSWORD_NOT_SET')[0])
flash('Error: There was an issue logging you in')
return False
if not verify_and_update_password(self.password.data, self.user):
#self.password.errors.append(get_message('INVALID_PASSWORD')[0])
flash('Error: There was an issue logging you in')
return False
if requires_confirmation(self.user):
#self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
flash('Error: You have not confirmed your email')
return False
if not self.user.is_active:
#self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
flash('Error: There was an issue logging you in')
return False
I'm not sure if there is a better way to implement the change I've put in than editing the package directly (I'm sure it's bad practice), but it worked for me, and I understand it.