consumes haveibeenpwned API directly

This commit is contained in:
sebastien 2024-11-04 08:55:55 +01:00
parent 8af6263b2f
commit 0acbb40ecd
3 changed files with 29 additions and 0 deletions

View file

@ -84,6 +84,31 @@ def password_strength_calculator(password):
return strength_score return strength_score
def pwned_password_validator(form, field):
try:
from hashlib import sha1
import requests
except ImportError:
return None
hashed_password = sha1(field.data.encode("utf-8")).hexdigest()
hashed_password_splited = (hashed_password[:5].upper(), hashed_password[5:].upper())
try:
response = requests.api.get(
f"https://api2.pwnedpasswords.com/range/{hashed_password_splited[0]}",
timeout=10,
)
except requests.exceptions.HTTPError as e:
print("Error: " + str(e))
decoded_response = response.content.decode("utf8").split("\r\n")
for each in decoded_response:
if hashed_password_splited[1] == each.split(":")[0]:
raise wtforms.ValidationError(_("This password is compromised."))
def email_validator(form, field): def email_validator(form, field):
try: try:
import email_validator # noqa: F401 import email_validator # noqa: F401

View file

@ -37,6 +37,7 @@ from canaille.app.forms import TableForm
from canaille.app.forms import is_readonly from canaille.app.forms import is_readonly
from canaille.app.forms import password_length_validator from canaille.app.forms import password_length_validator
from canaille.app.forms import password_too_long_validator from canaille.app.forms import password_too_long_validator
from canaille.app.forms import pwned_password_validator
from canaille.app.forms import set_readonly from canaille.app.forms import set_readonly
from canaille.app.forms import set_writable from canaille.app.forms import set_writable
from canaille.app.i18n import gettext as _ from canaille.app.i18n import gettext as _
@ -316,6 +317,7 @@ def registration(data=None, hash=None):
wtforms.validators.DataRequired(), wtforms.validators.DataRequired(),
password_length_validator, password_length_validator,
password_too_long_validator, password_too_long_validator,
pwned_password_validator,
] ]
form["password2"].validators = [ form["password2"].validators = [
wtforms.validators.DataRequired(), wtforms.validators.DataRequired(),

View file

@ -15,6 +15,7 @@ from canaille.app.forms import is_uri
from canaille.app.forms import password_length_validator from canaille.app.forms import password_length_validator
from canaille.app.forms import password_too_long_validator from canaille.app.forms import password_too_long_validator
from canaille.app.forms import phone_number from canaille.app.forms import phone_number
from canaille.app.forms import pwned_password_validator
from canaille.app.forms import set_readonly from canaille.app.forms import set_readonly
from canaille.app.forms import unique_values from canaille.app.forms import unique_values
from canaille.app.i18n import gettext from canaille.app.i18n import gettext
@ -265,6 +266,7 @@ PROFILE_FORM_FIELDS = dict(
wtforms.validators.Optional(), wtforms.validators.Optional(),
password_length_validator, password_length_validator,
password_too_long_validator, password_too_long_validator,
pwned_password_validator,
], ],
render_kw={ render_kw={
"autocomplete": "new-password", "autocomplete": "new-password",