Les systèmes d’authentification jouent un rôle crucial dans la fourniture d’une expérience utilisateur transparente et sécurisée. Un flux de travail d’authentification implique généralement deux processus : l’inscription et la connexion.


Avec l’augmentation du nombre de services en ligne, les utilisateurs créent des comptes et chaque compte nécessite des identifiants de connexion uniques. Cependant, il est facile d’oublier ou de confondre les identifiants de connexion. Pour y remédier, votre application doit mettre en œuvre une fonction de réinitialisation du mot de passe qui permet à l’utilisateur de réinitialiser son mot de passe de manière pratique et sécurisée.

Configurer le projet React

Vous pouvez mettre en œuvre un flux de travail de réinitialisation de mot de passe de différentes manières – il n’y a pas de norme universelle que chaque application devrait suivre. Au contraire, vous devez adapter l’approche que vous choisissez aux besoins spécifiques de votre application.

Le flux de travail que vous découvrirez ici comprend les étapes suivantes :

Flux de travail de réinitialisation du mot de passe

Pour commencer, démarrez rapidement un projet React. Ensuite, installez Axios, une bibliothèque de requêtes HTTP JavaScript.

 npm install axios 

Vous pouvez trouver le code du projet dans ce dépôt GitHub.

Créer un composant de connexion

Dans le répertoire src, créez un nouveau composant composants/Login.js et ajoutez le code suivant. Commencez par définir le processus de réinitialisation du mot de passe :

 import axios from "axios";
import React, { useState } from "react";
import { useContext } from "react";
import { RecoveryContext } from "../App";
import "./global.component.css";

export default function Login() {
  const { setPage, setOTP, setEmail } = useContext(RecoveryContext);
  const [userEmail, setUserEmail] = useState("");

  function sendOtp() {
    if (userEmail) {
      axios.get(`http://localhost:5000/check_email?email=${userEmail}`).then((response) => {
        if (response.status === 200) {
          const OTP = Math.floor(Math.random() * 9000 + 1000);
          console.log(OTP);
          setOTP(OTP);
          setEmail(userEmail);

          axios.post("http://localhost:5000/send_email", {
            OTP,
            recipient_email: userEmail,
          })
          .then(() => setPage("otp"))
          .catch(console.log);
        } else {
          alert("User with this email does not exist!");
          console.log(response.data.message);
        }}).catch(console.log);
    } else {
      alert("Please enter your email");
    }}

Ce code crée une fonction qui envoie un mot de passe à usage unique (OTP) à l’adresse électronique d’un utilisateur. Il vérifie d’abord l’utilisateur en contrôlant son adresse électronique dans la base de données avant de générer et d’envoyer l’OTP. Enfin, elle met à jour l’interface utilisateur avec la page OTP.

Compléter le composant de connexion en ajoutant du code pour rendre l’élément de formulaire JSX de connexion :

   return (
    <div>
      <h2>Login</h2>

      <form>
        <label /> Email:
        <input type="email" value={userEmail} onChange={(e) => { setUserEmail(e.target.value) }} />

        <label /> Password:
        <input type="password" />

        <button type="submit">login</button>
      </form>
      <a href="#" onClick={() => sendOtp()}>
        Forgot Password
      </a>
    </div>
  );
}

Créer un composant de vérification OTP

Pour s’assurer de la validité d’un code saisi par un utilisateur, il faut le comparer au code envoyé à son e-mail.

Créer un nouveau composants/OTPInput.js et ajoutez ce code :

 import React, { useState, useContext, useEffect } from "react";
import { RecoveryContext } from "../App";
import axios from "axios";
import "./global.component.css";

export default function OTPInput() {
  const { email, otp, setPage } = useContext(RecoveryContext);
  const [OTPinput, setOTPinput] = useState( "");

  function verifyOTP() {
    if (parseInt(OTPinput) === otp) {
      setPage("reset");
    } else {
      alert("The code you have entered is not correct, try again re-send the link");
    }
  }

Ce code crée un composant React dans lequel les utilisateurs vérifient leur code OTP. Il vérifie que le code saisi correspond à celui stocké dans l’objet contextuel. S’il est valide, il affiche la page de réinitialisation du mot de passe. Dans le cas contraire, il affiche une alerte invitant l’utilisateur à réessayer ou à renvoyer l’OTP.

Vous pouvez consulter le code dans ce dépôt qui implémente une fonction pour renvoyer les OTP et un délai d’expiration pour le code OTP.

Enfin, rendez les éléments JSX d’entrée.

   return (
    <div>
      <h3>Email Verification</h3>
      <p>We have sent a verification code to your email.</p>
      <form>
         <input type="text" value={OTPinput} onChange={(e) => { setOTPinput(e.target.value) }} />
          <button onClick={() => verifyOTP()}>Verify Account</button>
          <a onClick={() => resendOTP()} > Didn't receive code?
            {disable ? `Resend OTP in ${timerCount}s` : " Resend OTP"}
          </a>
      </form>
    </div>
  );}

Créer le composant de réinitialisation du mot de passe

Créer un nouveau composants/Reset.js et ajoutez ce code :

 import React, {useState, useContext} from "react";
import { RecoveryContext } from "../App";
import axios from "axios";
import "./global.component.css";

export default function Reset() {
  const [password, setPassword] = useState("");
  const { setPage, email } = useContext(RecoveryContext);

  function changePassword() {
    if (password) {
      try {
        axios.put("http://localhost:5000/update-password", {
          email:email,
          newPassword: password,
        }).then(() => setPage("login"));

        return alert("Password changed successfully, please login!");
      } catch (error) {console.log(error);}}
    return alert("Please enter your new Password");
 }

  return (
    <div>
      <h2> Change Password </h2>
        <form>
          <label /> New Password:
          <input
            type="password"
            placeholder="........"
            required=""
            value={password}
            onChange={(e) => setPassword(e.target.value)} />
          <button onClick={() => changePassword()}>Reset passwod </button>
        </form>
    </div>
  );
}

Ce code génère un formulaire qui permet aux utilisateurs de saisir un nouveau mot de passe. Lorsque l’utilisateur clique sur soumettre, il envoie une requête au serveur pour mettre à jour son mot de passe dans la base de données. Il met ensuite à jour l’interface utilisateur si la requête aboutit.

Mettre à jour votre composant App.js

Apportez les modifications ci-dessous à votre fichier src/App.js :

 import { useState, createContext } from "react";
import Login from "./components/Login";
import OTPInput from "./components/OTPInput";
import Reset from "./components/Reset";
import "./App.css";
export const RecoveryContext = createContext();

export default function App() {
  const [page, setPage] = useState("login");
  const [email, setEmail] = useState("");
  const [otp, setOTP] = useState("");

  function NavigateComponents() {
    if (page === "login") return <Login />;
    if (page === "otp") return <OTPInput />;
    if (page === "reset") return <Reset />;
  }

  return (
    <div className="App-header">
      <RecoveryContext.Provider
        value={{ page, setPage, otp, setOTP, email, setEmail }}>
        <div>
          <NavigateComponents />
        </div>
      </RecoveryContext.Provider>
    </div>
  );
}

Ce code définit un objet contextuel qui gère l’état de l’application, à savoir l’adresse électronique de l’utilisateur, le code OTP et les différentes pages de l’application. Essentiellement, l’objet contextuel permet de transmettre les états requis entre les différents composants – une alternative à l’utilisation des props.

Il comprend également une fonction qui gère facilement la navigation dans les pages sans qu’il soit nécessaire de redessiner des composants entiers.

La mise en place d’un serveur Express.js

Une fois le client configuré, configurez un service d’authentification dorsal pour gérer la fonctionnalité de réinitialisation du mot de passe.

Pour commencer, créez un serveur web Express et installez les paquets suivants :

 npm install cors dotenv nodemailer mongoose 

Ensuite, créez une base de données MongoDB ou configurez un cluster MongoDB sur le cloud. Copiez ensuite la chaîne de connexion fournie, créez un fichier ENV dans le répertoire racine et collez la chaîne de connexion.

Pour terminer, vous devez configurer la connexion à la base de données et définir les modèles de données pour vos données utilisateur. Utilisez le code de ce référentiel pour configurer la connexion à la base de données et définir les modèles de données.

Définir les routes API

Un service backend possède idéalement plusieurs routes qui gèrent les requêtes HTTP des clients. Dans ce cas, vous devrez définir trois routes qui géreront les requêtes API send-email, email verification et update-password du client React.

Créez un nouveau fichier appelé userRoutes.js dans le répertoire racine et ajoutez le code suivant :

 const express = require('express');
const router = express.Router();
const userControllers = require('../controllers/userControllers');

router.get('/check_email', userControllers.checkEmail);
router.put('/update-password', userControllers.updatePassword);
router.post('/send_email', userControllers.sendEmail);

module.exports = router;

Contrôleurs pour les routes API

Les contrôleurs sont chargés de traiter les demandes HTTP des clients. Une fois qu’un client fait une demande à une route API particulière, une fonction du contrôleur est invoquée et exécutée pour traiter la demande et renvoyer une réponse appropriée.

Créer un nouveau controllers/userControllers.js et ajoutez le code ci-dessous.

Utilisez le code de ce référentiel pour définir des contrôleurs pour les routes API de vérification de l’email et de mise à jour du mot de passe.

Commencez par définir le contrôleur d’envoi d’email :

 exports.sendEmail = (req, res) => {
  const transporter = nodemailer.createTransport({
    service: 'gmail',
    secure: true,
    auth: {
      user: process.env.MY_EMAIL,
      pass: process.env.APP_PASSWORD,
    },
  });

  const { recipient_email, OTP } = req.body;

  const mailOptions = {
    from: process.env.MY_EMAIL,
    to: recipient_email,
    subject: 'PASSWORD RESET',
    html: `<html>
             <body>
               <h2>Password Recovery</h2>
               <p>Use this OTP to reset your password. OTP is valid for 1 minute</p>
               <h3>${OTP}</h3>
             </body>
           </html>`,
  };

  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      console.log(error);
      res.status(500).send({ message: "An error occurred while sending the email" });
    } else {
      console.log('Email sent: ' + info.response);
      res.status(200).send({ message: "Email sent successfully" });
    }
  });
};

Ce code définit une fonction qui utilise Nodemailer pour envoyer un courriel avec une réinitialisation OTP à un destinataire spécifié. Il met en place un transporteur en utilisant votre propre compte Gmail et votre mot de passe.

Pour obtenir le mot de passe de votre application Gmail, vous devez générer un mot de passe d’application dans les paramètres de votre compte Google. Vous utiliserez ensuite ce mot de passe à la place de votre mot de passe Gmail habituel pour authentifier le Nodemailer.

Configurer le point d’entrée du serveur

Créez un fichier server.js dans le répertoire racine et ajoutez ce code :

 const express = require('express');
const cors = require('cors');
const app = express();
const port = 5000;
require('dotenv').config();
const nodemailer = require('nodemailer');
const connectDB = require('./utils/dbconfig');
connectDB();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
const userRoutes = require('./routes/userRoutes');
app.use("https://www.makeuseof.com/", userRoutes);

app.listen(port, () => {
  console.log(`Server is listening at http://localhost:${port}`);
});

Une fois le client et le serveur configurés, vous pouvez exécuter les serveurs de développement pour tester la fonctionnalité du mot de passe.

Création d’un service personnalisé de réinitialisation de mot de passe

Créer un système de réinitialisation de mot de passe en l’adaptant à votre application et à ses utilisateurs est la meilleure approche, même s’il existe des solutions payantes et préconstruites. Lors de la conception de cette fonctionnalité, vous devez tenir compte à la fois de l’expérience utilisateur et de la sécurité, car les attaques sont une menace constante.