Menu

Réinitialisation du mot de passe – Authentification Django 2° partie

Authentication system

[Source image : stories – fr.freepik.com ]

Cet article constitue la deuxième partie de notre tutoriel “Un système d’authentification pour votre application Django” et nous verrons ici comment implémenter la réinitialisation du mot de passe avec Django. Dans l’article précédent, on avait construit une application de prise de notes où les utilisateurs inscrits pouvaient se connecter pour consulter leurs notes et se déconnecter après avoir fini.

Dans cet article, nous allons ajouter une autre fonctionnalité qui peut être très utile lorsqu’un utilisateur a oublié son mot de passe ou veut simplement le modifier pour des raisons de sécurité. En effet, un utilisateur doit être en mesure de changer ou de réinitialiser son mot de passe pour accéder à son espace dans l’application. Nous allons pour cela utiliser le système d’authentification par défaut fourni par le Framework Django.

Ce système offre entre autres la possibilité de changer le mot de passe de l’utilisateur, en demandant à celui-ci de fournir une adresse e-mail, à laquelle sera envoyée un lien permettant d’effectuer le changement de mot de passe.

Le code source de l’application qu’on nous construisons est sur GitHub.

Le système de réinitialisation de mot de passe par défaut

Les pages associées à l’opération de réinitialisation de mot de passe sont définies par défaut et sont liées au portail d’administration. Avant de les tester, voyons quelles sont elles :

password_reset : présente à l’utilisateur le formulaire dans lequel il va soumettre son adresse e-mail.

password_reset_done : page vers laquelle l’utilisateur est redirigé après avoir soumis l’adresse e-mail.

password_reset_email : correspond au contenu du message envoyé à l’utilisateur. Ce message contient le lien vers lequel l’utilisateur est dirigé pour réinitialiser son mot de passe.

password_reset_confirm : correspond au lien qui est envoyé à l’utilisateur sur son adresse e-mail. Dans cette page, l’utilisateur a la possibilité de saisir un nouveau mot de passe.

password_reset_complete : page vers laquelle l’utilisateur est redirigé après avoir changé son mot de passe.

Rappelons que les chemins vers ces pages sont définis dans le fichier urls.py de usersapp. La ligne path('accounts/', include('django.contrib.auth.urls')) dans le fichier urls.py inclut les lignes suivantes :

accounts/ password_reset/ [name='password_reset']
accounts/ password_reset/done/ [name='password_reset_done']
accounts/ reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/ reset/done/ [name='password_reset_complete']

NOTE Pour plus d’informations sur ces pages, vous pouvez consulter la documentation officielle de Django à ce sujet.

Tester les pages par défaut

Tout d’abord, à des fins de test durant le développement en local, ajoutons EMAIL_BACKEND dans le fichier de configuration du projet settings.py pour simuler l’envoi d’e-mail de réinitialisation de mot de passe sur console.

...
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
...

INFO Pour que l’envoi d’e-mail fonctionne, l’adresse doit être enregistrée dans la base de données.

Avant de continuer, voyons à quoi ressemblent ces pages. Dans notre exemple, supposons qu’Alice (l’utilisateur créé en première partie du tutoriel) veuille se connecter mais qu’elle a oublié son mot de passe. Celle-ci devrait avoir accès à une option lui permettant de le réinitialiser. Nous allons commencer par fournir cette option en modifiant la page de connexion pour y ajouter l’url de la page de réinitialisation par défaut (ligne 34) :

{% extends "base.html" %}
{% block content %}
<h2>Se connecter </h2>
<div>
    <form method="post">
        {% csrf_token %}
        {% if form.non_field_errors %}
            {% for error in form.non_field_errors %}
            <p class="alert alert-danger">{{ error }}</p>
            {% endfor %}
        {% endif %}
        {% csrf_token %}
        <table>
        {% for field in form %}
          <tr>
            <td>{{ field.label_tag }}</td>
            <td>{{ field }}</td>
          </tr>
          
        {% endfor %}
         </table>
        <button type="submit">se connecter</button>
    </form>
</div>

<div>
    <small>
        Pas encore inscrit.e?
        <a href="#">
            S'inscrire
        </a>
    <br>
        Mot de passe oublié ?
        <a href="{% url 'password_reset' %}">
            Renouveler mon mot de passe
        </a>
    </small>
</div>
{% endblock %}

Après avoir lancé le serveur de développement, vous pouvez accéder à la page d’accueil de l’application qui vous redirigera vers la page de connexion.

Réinitialisation du mot de passe

En cliquant sur le lien Renouveler mon mot de passe, Alice est redirigée vers la page “password_reset” fournie par Django. On peut voir que celle-ci est liée au portail d’administration Django. Alice est invitée à saisir son adresse e-mail (indiquée lors de son ajout, en première partie, dans le portail d’administration).

Confirmation de l’envoi du message de réinitialisation

Lorsque Alice soumet son adresse e-mail, la page “password_reset_done” confirmant l’envoi d’un message à cette adresse s’affiche dans son navigateur.

Message de réinitialisation

Etant donnée que nous sommes dans un environnement de développement et que nous ne faisons qu’une simulation avec une adresse e-mail fictive ([email protected]), le message “password_reset_email” s’affiche au niveau de l’invite de commandes.

Dans le message, on peut observer un lien vers la page de réinitialisation fourni à Alice. Il lui suffit de copier le lien dans la barre d’adresse de son navigateur pour accéder à ladite page.

Formulaire de réinitialisation

Dans la page “password_reset_confirm” , Alice peut saisir son nouveau mot de passe.

Confirmation de réinitialisation du mot de passe

Après le changement du mot de passe, Alice est redirigée vers une page “password_reset_complete” confirmant la mise à jour de son mot de passe.

Nous aurons à personnaliser chacune de ces pages, mais ne vous inquiétez pas, ce sera très rapide!

Redéfinir les pages de réinitialisation de mot de passe

Bien évidement, nous ne voulons pas que les utilisateurs de l’application accèdent au templates par défaut du système d’authentification liées au portail d’administration. Il nous faut créer nos propres templates et les lier aux vues existantes.

Nous commençons par redéfinir les chemins associés aux templates que nous allons créer juste après comme ceci :

...
from django.contrib.auth import views as auth_views

urlpatterns =[
  	...,
    path('password_reset/', auth_views.PasswordResetView.as_view(template_name='registration/password_reset.html'), name = 'password_reset'),
	path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(template_name='registration/password_reset_done.html'), name='password_reset_done'),
	path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='registration/password_reset_confirm.html'), name='password_reset_confirm'),
    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(template_name='registration/password_reset_complete.html'), name='password_reset_complete'),
]

Ces chemins redéfinissent les templates liées aux vues d’authentification existantes de Django.

Créons maintenant les différents templates associés à nos différentes vues.

Réinitialisation du mot de passe

Ce premier template est le formulaire dans lequel l’utilisateur indique son adresse e-mail. C’est à cette adresse qu’il recevra le message contenant le lien vers la page de réinitialisation.

{% extends "base.html" %}
{% block content %}
<h2>Réinitialisation du mot de passe </h2>
<p>Mot de passe perdu ? Saisissez votre adresse électronique ci-dessous et nous vous enverrons les instructions pour en créer un nouveau.</p>
<form method="post">
	{% csrf_token %}
	{% if form.email.errors %}
		{% for error in form.email.errors %}
		<p class="alert alert-danger">{{ error }}</p>
		{% endfor %}
	{% endif %}
	<p>{{ form.email.label_tag }} {{ form.email }}</p>
	<button type="submit">M'envoyer les instructions</button>
</form>
{% endblock %}

Confirmation de l’envoi du message de réinitialisation

Ce template est un simple message de confirmation d’envoi du message de réinitialisation.

{% extends "base.html" %}
{% block content %}
<h2>Message de réinitialisation du mot de passe envoyé</h2>
<p>Nous vous avons envoyé par courriel les instructions pour changer de mot de passe, pour autant qu'un compte existe avec l'adresse que vous avez indiquée. Vous devriez recevoir rapidement ce message.</p>

<p>Si vous ne recevez pas de message, vérifiez que vous avez saisi l'adresse avec laquelle vous vous êtes enregistré et contrôlez votre dossier de pourriels.</p>
{% endblock %}

Message de réinitialisation

Ce fichier correspond au message envoyé à l’adresse e-mail soumise par l’utilisateur. Dans ce message, on communique le lien vers le formulaire de réinitialisation.

Vous avez demandé la réinitialisation de votre mot de passe en indiquant ce courriel {{ email }}. Cliquez sur le lien ci-dessous :
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

Formulaire de réinitialisation

Dans ce formulaire l’utilisateur saisit son nouveau mot de passe.

{% extends "base.html" %}
{% block content %}
{% if validlink %}
<h2>Réinitialisation de mot de passe </h2>
<p>Veuillez saisir votre nouveau mot de passe.</p>
<form method="post">
	{% csrf_token %}
	{% if form.new_password1.errors %}
		<ul class="alert alert-danger">
		{% for error in form.new_password1.errors %}
		 <li>{{ error }}</li>
		{% endfor %}
		</ul>
	{% endif %}
	{% if form.new_password2.errors %}
		<ul class="alert alert-danger">
		{% for error in form.new_password2.errors %}
		 <li>{{ error }}</li>
		{% endfor %}
		</ul>
	{% endif %}
	<table>		
		<tr>
			<td>
				<label for="id_new_password1">Mon nouveau mot de passe :</label>
			</td>
			<td>{{ form.new_password1 }}</td>
		</tr>
		<tr>
			<td>				
				<label for="id_new_password2">Confirmer mon nouveau mot de passe :</label>
			</td>
			<td>{{ form.new_password2 }}</td>
		</tr>
	</table>
	<button type="submit">Changer mon mot de passe</button>
</form>
{% else %}
<h2>Echec de réinitialisation du mot de passe</h2>
<p>Le lien de réinitialisation de mot de passe est invalide. Veuillez réessayer.</p>
{% endif %}
{% endblock %}

Confirmation de réinitialisation du mot de passe

L’utilisateur soumet son nouveau mot de passe et reçoit un message de confirmation via le template “password_reset_complete”.

{% extends "base.html" %}
{% block content %}
<h2>Mot de passe réinitialisé.</h2>
<p>Votre mot de passe a été réinitialisé avec succès.Revenir à <a href="{% url 'login' %}">la page de connexion</a>.</p>
{% endblock %}

N’oubliez pas de supprimer la ligne path('accounts/', include('django.contrib.auth.urls')) correspondant aux chemins d’authentification par défaut.

Conclusion

Dans cet article, nous avons vu comment utiliser et personnaliser le système de réinitialisation de mot de passe de Django en local. Nous pourrons voir dans un autre tutoriel comment utiliser ce système en production. Dans le prochain et dernier article de cette série consacrée au système d’authentification de Django, nous verrons comment un utilisateur peut s’inscrire sur un site web. Si vous avez des interrogations concernant cette seconde partie de tutoriel, nous pouvons en discuter en commentaires.