Réinitialisation de mot de passe
Ce que le framework fournit
Runique intègre un système complet, prêt à l'emploi :
- 2 routes auto-enregistrées (formulaire oubli + réinitialisation)
- 2 formulaires fournis (
ForgotPasswordForm,PasswordResetForm) - Génération et validation de tokens (UUID, TTL 1h, usage unique)
- Envoi automatique de l'email si le mailer est configuré
- Rate limiting intégré (5 requêtes / 5 min par défaut)
- Messages i18n inclus
- Une fois le reset réussi : toutes les sessions du compte fermées, ainsi que celle du navigateur où il a eu lieu (même connecté sous un autre compte) — dans la même transaction que le changement de mot de passe. Afficher le formulaire ne déconnecte personne
- Selon l'état du compte : lien d'activation (compte en attente), lien de réinitialisation (compte actif), email « compte bloqué » sans lien (compte désactivé) — la page répond toujours la même chose. Voir États d'un compte
Activation
RuniqueApp::builder(config)
.with_public_url("https://monsite.com")
.with_mailer_from_env()
.with_password_reset(|pr| pr)
.build()
.await?
Les liens envoyés par email partent de l'URL publique du site, définie dans le builder par .with_public_url("https://monsite.com") (voir Builder).
En production, l'application refuse de démarrer sans elle : sinon le lien serait construit à partir de l'en-tête Host de la requête, qu'un attaquant choisit (Host: evil.com → le jeton de la victime part chez lui). En debug, le Host reste le repli, avec un avertissement.
Les comptes sont ceux de
eihwaz_users, la table utilisateur du framework — à enrichir avecextend!{ table: "eihwaz_users", ... }.
Configuration
Toutes les options sont optionnelles — les valeurs par défaut fonctionnent sans rien changer.
.with_password_reset(|pr| pr
.forgot_route("/mot-de-passe-oublie") // défaut : /forgot-password
.reset_route("/reinitialiser") // défaut : /reset-password
.forgot_template("auth/oubli.html") // défaut : auth/forgot_password.html
.reset_template("auth/reset.html") // défaut : auth/reset_password.html
.email_template("emails/reset.html") // défaut : template intégré
.success_redirect("/connexion") // défaut : /
.token_ttl(Duration::from_secs(1800)) // défaut : 1h (std::time::Duration)
)
Templates
Deux templates sont à créer dans templates/. Si absents, le framework utilise ses propres templates par défaut.
auth/forgot_password.html — formulaire "email oublié"
{% extends "base.html" %}
{% block content %}
<form method="post">
{{ form.html | safe }}
<button type="submit">Envoyer le lien</button>
</form>
{% if form.errors.email %}
<p class="error">{{ form.errors.email }}</p>
{% endif %}
{% endblock %}
Variables disponibles dans le contexte Tera :
| Variable | Description |
|---|---|
form | Formulaire avec champ email |
form.errors | Erreurs de validation |
auth/reset_password.html — formulaire de reset
{% extends "base.html" %}
{% block content %}
<form method="post">
{{ form.html | safe }}
<button type="submit">Changer le mot de passe</button>
</form>
{% if form.errors.password %}
<p class="error">{{ form.errors.password }}</p>
{% endif %}
{% endblock %}
Variables disponibles :
| Variable | Description |
|---|---|
form | Formulaire avec un token caché et les champs email, password et confirm |
form.errors | Erreurs de validation |
Validations automatiques : mot de passe minimum 10 caractères, confirmation identique, token valide et non expiré, et email saisi correspondant au compte lié au token.
Flux complet
1. Utilisateur clique "Mot de passe oublié"
↓
2. GET /forgot-password → affiche le formulaire email
↓
3. POST /forgot-password → email soumis
- Si l'email existe : génère un token (1h), envoie un email avec le lien
- Si l'email est inconnu : même réponse (sécurité — ne révèle pas les comptes existants)
↓
4. Utilisateur clique le lien reçu par email
↓
5. GET /reset-password/{token} → affiche le formulaire de reset
- Token invalide ou expiré → erreur
↓
6. POST /reset-password/{token}
- Valide le formulaire et compare l'email saisi au compte lié au token
- Consomme le token (usage unique)
- Met à jour le mot de passe en DB
- Redirige vers success_redirect (défaut : /)
Sessions actives après reset : une fois le nouveau mot de passe enregistré, toutes les sessions du compte sont fermées, sur tous les appareils — une session volée comprise —, ainsi que la session du navigateur qui a fait le reset. Le tout se fait dans la transaction du changement de mot de passe : si la base refuse, rien n'est changé et le lien reste utilisable. Un seul lien est actif par compte : une nouvelle demande remplace le précédent. L'utilisateur se reconnecte avec le nouveau mot de passe. Les autres comptes ne sont pas touchés. Seuls les stores de Runique sont concernés : un store branché avec
with_session_store()(Redis…) ne peut pas être parcouru par utilisateur — voir Révocation des sessions.
Intégration admin
Si l'admin est activé avec .user_resource(), le panel peut envoyer des liens de reset directement depuis la fiche utilisateur.
Le lien part de l'URL publique (.with_public_url()) et de la route du reset configurée (reset_route, /reset-password par défaut) : rien à régler côté admin. Sans mailer configuré, le lien s'affiche dans un flash message.
Template email admin (optionnel, sinon template par défaut) :
templates/admin/reset_password_email.htmltemplates/admin/user_created_email.html
Variables disponibles dans ces templates : username, email, reset_url.
Sans mailer configuré
Le mailer est optionnel. Si absent :
- En développement : le lien de reset s'affiche dans un flash message dans l'admin
- Côté formulaire oublié : le message de succès s'affiche mais aucun email n'est envoyé
Pour tester en dev sans serveur SMTP :
EMAIL_BACKEND=consoleimprime l'email dans le terminal.
← Authentification | Mailer →