Un lien "Mot de passe oublié ?" (login.html) mène à /forgot-password : si l'adresse saisie correspond à un compte, un jeton à haute entropie (secrets.token_urlsafe, valable 1h) est généré et envoyé par email via smtplib (auth/send_email.py, aucune dépendance ajoutée) — configuré uniquement par variables d'environnement (SMTP_HOST/PORT/USER/PASSWORD/ FROM, voir .env.example et docker-compose.prod.yml), n'importe quel serveur SMTP existant convient (Mailcow compris). Seul le hash SHA-256 du jeton est stocké (auth/password_reset.py, table _password_reset_tokens) : un jeton envoyé par email reste inutilisable même en cas de fuite de la base. Le même message générique s'affiche que l'adresse corresponde à un compte ou non, pour ne jamais permettre à ce formulaire de servir à deviner quelles adresses sont déjà inscrites. Un échec d'envoi (SMTP non configuré) est journalisé côté serveur seulement, jamais révélé à l'utilisateur. /reset-password/<token> vérifie le jeton (non expiré, non déjà utilisé), applique les mêmes règles de mot de passe fort qu'à l'inscription (même schéma visuel), puis consomme le jeton et remet à zéro le compteur anti-bruteforce du compte (auth/set_password.py) — une identité prouvée par email est une voie de récupération légitime même pour un compte verrouillé. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
18 lines
654 B
Python
18 lines
654 B
Python
from werkzeug.security import generate_password_hash
|
|
|
|
from .connection import connect
|
|
|
|
|
|
def set_password(user_id, new_password):
|
|
"""Remet aussi le compteur anti-bruteforce à zéro (auth/rate_limit.py) :
|
|
prouver son identité par email est une voie de récupération légitime,
|
|
un compte verrouillé après trop d'échecs ne doit pas rester bloqué une
|
|
fois le mot de passe changé pour de vrai."""
|
|
conn = connect()
|
|
conn.execute(
|
|
"UPDATE _users SET password_hash = ?, failed_attempts = 0, locked_until = NULL WHERE id = ?",
|
|
(generate_password_hash(new_password), user_id),
|
|
)
|
|
conn.commit()
|
|
conn.close()
|