Fonctionnalités d'authentification avancées

1. Configurer

Obtenir le code source

Dans cet atelier de programmation, vous allez commencer avec une version presque complète de l'application exemple Friendly Chat. La première chose à faire est donc de cloner le code source :

$ git clone https://github.com/firebase/codelab-friendlychat-web --branch security

Accédez ensuite au répertoire security-start, dans lequel vous travaillerez pour le reste de cet atelier de programmation :

$ cd codelab-friendlychat-web/security-start

Installez maintenant les dépendances pour pouvoir exécuter le code. Si votre connexion Internet est lente, cette opération peut prendre une ou deux minutes :

$ npm install && (cd functions && npm install)

Découvrir ce dépôt

Le répertoire security-solution/ contient le code complet de l'application exemple. Le répertoire security-start est celui dans lequel vous allez travailler tout au long de l'atelier de programmation. Il manque quelques éléments importants de l'implémentation de l'authentification. Voici les principaux fichiers et fonctionnalités de security-start/ et security-solution/ :

  • functions/index.js contient le code Cloud Functions et c'est là que vous écrirez les fonctions de blocage de l'authentification.
  • public/ : contient les fichiers statiques de votre application de chat
  • public/scripts/main.js : emplacement où le code JS de votre application de chat (src/index.js) est compilé
  • src/firebase-config.js : contient l'objet de configuration Firebase utilisé pour initialiser votre application de chat.
  • src/index.js : code JS de votre application de chat

Obtenir la CLI Firebase

La suite d'émulateurs fait partie de la CLI Firebase (interface de ligne de commande), qui peut être installée sur votre machine avec la commande suivante :

$ npm install -g firebase-tools@latest

Créez le fichier JavaScript avec webpack, ce qui créera main.js dans le répertoire public/scripts/.

webpack build

Ensuite, vérifiez que vous disposez de la dernière version de la CLI. Cet atelier de programmation fonctionne avec la version 11.14 ou ultérieure.

$ firebase --version
11.14.2

Se connecter à votre projet Firebase

Créer un projet Firebase

  1. Connectez-vous à la console Firebase à l'aide de votre compte Google.
  2. Cliquez sur le bouton pour créer un projet, puis saisissez un nom de projet (par exemple, Authentication MFA Codelab).
  3. Cliquez sur Continuer.
  4. Si vous y êtes invité, lisez et acceptez les Conditions d'utilisation de Firebase, puis cliquez sur Continuer.
  5. (Facultatif) Activez l'assistance IA dans la console Firebase (appelée "Gemini dans Firebase").
  6. Pour cet atelier de programmation, vous n'avez pas besoin de Google Analytics. Désactivez donc l'option Google Analytics.
  7. Cliquez sur Créer un projet, attendez que votre projet soit provisionné, puis cliquez sur Continuer.

Associer votre code à votre projet Firebase

Vous devez maintenant associer ce code à votre projet Firebase. Commencez par exécuter la commande suivante pour vous connecter à la CLI Firebase :

$ firebase login

Exécutez ensuite la commande suivante pour créer un alias de projet. Remplacez $YOUR_PROJECT_ID par l'ID de votre projet Firebase.

$ firebase use $YOUR_PROJECT_ID

Vous êtes maintenant prêt à exécuter l'application.

2. Exécuter les émulateurs

Dans cette section, vous allez exécuter l'application en local. Il est donc temps de démarrer l'Emulator Suite.

Démarrer les émulateurs

Depuis le répertoire source du codelab, exécutez la commande suivante pour démarrer les émulateurs :

$ firebase emulators:start

Votre application sera diffusée à l'adresse http://127.0.0.1:5170 et votre code source sera recompilé en continu à mesure que vous le modifierez. Pour voir vos modifications, il vous suffit d'actualiser votre navigateur (Ctrl+Maj+R).

Le résultat devrait ressembler à ceci :

i  emulators: Starting emulators: auth, functions, firestore, hosting, storage
✔  functions: Using node@16 from host.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[demo-example]: Serving hosting files from: ./public
✔  hosting[demo-example]: Local server: http://127.0.0.1:5170
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "[...]" for Cloud Functions...
✔  functions: Loaded functions definitions from source: beforecreated.
✔  functions[us-central1-beforecreated]: providers/cloud.auth/eventTypes/user.beforeCreate function initialized (http://127.0.0.1:5011/[...]/us-central1/beforecreated).
i  Running script: npm start
 
> security@1.0.0 start
> webpack --watch --progress
[...]
webpack 5.50.0 compiled with 1 warning in 990 ms

Une fois le message Tous les émulateurs sont prêts affiché, l'application est prête à être utilisée.

3. Implémenter l'authentification multifacteur

L'authentification multifactorielle a été partiellement implémentée dans ce dépôt. Vous allez ajouter le code pour d'abord inscrire un utilisateur à l'authentification multifacteur, puis pour demander aux utilisateurs inscrits à l'authentification multifacteur un deuxième facteur.

Dans votre éditeur, ouvrez le fichier src/index.js et recherchez la méthode startEnrollMultiFactor(). Ajoutez le code suivant pour configurer l'outil de vérification reCAPTCHA qui empêchera l'utilisation abusive du téléphone (l'outil de vérification reCAPTCHA est défini comme invisible et ne sera pas visible par les utilisateurs) :

async function startEnrollMultiFactor(phoneNumber) {
  const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha",
    { size: "invisible" },
    getAuth()
  );

Ensuite, recherchez la méthode finishEnrollMultiFactor() et ajoutez ce qui suit pour enregistrer le deuxième facteur :

// Completes MFA enrollment once a verification code is obtained.
async function finishEnrollMultiFactor(verificationCode) {
  // Ask user for the verification code. Then:
  const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
  const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
 
  // Complete enrollment.
  await multiFactor(getAuth().currentUser)
    .enroll(multiFactorAssertion)
    .catch(function (error) {
      alert(`Error finishing second factor enrollment. ${error}`);
      throw error;
    });
  verificationId = null;
}

Ensuite, recherchez la fonction signIn et ajoutez le flux de contrôle suivant qui invite les utilisateurs inscrits à l'authentification multifacteur à saisir leur deuxième facteur :

async function signIn() {
  // Sign in Firebase using popup auth and Google as the identity provider.
  var provider = new GoogleAuthProvider();
  await signInWithPopup(getAuth(), provider)
    .then(function (userCredential) {
      // User successfully signed in and is not enrolled with a second factor.
    })
    .catch(function (error) {
      if (error.code == "auth/multi-factor-auth-required") {
        multiFactorResolver = getMultiFactorResolver(getAuth(), error);
        displaySecondFactor(multiFactorResolver.hints);
      } else {
        alert(`Error signing in user. ${error}`);
      }
    });
}

Le reste de l'implémentation, y compris les fonctions appelées ici, est déjà terminé. Pour voir comment ils fonctionnent, parcourez le reste du fichier.

4. Essayer de se connecter avec l'authentification multifactor dans les émulateurs

Testez maintenant l'implémentation de l'authentification multifactorielle. Assurez-vous que vos émulateurs sont toujours en cours d'exécution et accédez à l'application hébergée localement sur localhost:5170. Essayez de vous connecter. Lorsque vous êtes invité à fournir le code MFA, celui-ci s'affiche dans la fenêtre du terminal.

Comme les émulateurs sont entièrement compatibles avec l'authentification multifactorielle, votre environnement de développement peut être entièrement autonome.

Pour en savoir plus sur l'implémentation de l'authentification multifactorielle, consultez notre documentation de référence.

5. Créer une fonction de blocage

Certaines applications ne sont destinées qu'à un groupe d'utilisateurs spécifique. Dans ce cas, vous devez pouvoir créer des exigences personnalisées pour qu'un utilisateur puisse s'inscrire ou se connecter à votre application.

C'est ce que proposent les fonctions de blocage : un moyen de créer des exigences d'authentification personnalisées. Il s'agit de fonctions Cloud Functions, mais contrairement à la plupart des fonctions, elles s'exécutent de manière synchrone lorsqu'un utilisateur tente de s'inscrire ou de se connecter.

Pour créer une fonction de blocage, ouvrez functions/index.js dans votre éditeur et recherchez la fonction beforecreated mise en commentaire.

Remplacez-le par le code suivant, qui autorise uniquement les utilisateurs disposant d'un domaine example.com à créer un compte :

exports.beforecreated = beforeUserCreated((event) => {
  const user = event.data;
  // Only users of a specific domain can sign up.
  if (!user.email || !user.email.endsWith("@example.com")) {
    throw new HttpsError("invalid-argument", "Unauthorized email");
  }
});

6. Essayer la fonction de blocage dans les émulateurs

Pour tester la fonction de blocage, assurez-vous que vos émulateurs sont en cours d'exécution et déconnectez-vous de l'application Web à l'adresse localhost:5170.

Ensuite, essayez de créer un compte avec une adresse e-mail qui ne se termine pas par example.com. La fonction de blocage empêchera l'opération de réussir.

Réessayez avec une adresse e-mail se terminant par example.com. Le compte sera créé.

Les fonctions de blocage vous permettent de créer les restrictions dont vous avez besoin concernant l'authentification. Pour en savoir plus, consultez la documentation de référence.

Résumé

Bravo ! Vous avez ajouté l'authentification multifacteur à une application Web pour aider les utilisateurs à sécuriser leur compte, puis vous avez créé des exigences personnalisées pour que les utilisateurs s'inscrivent à l'aide de fonctions de blocage. Vous avez bien mérité un GIF !

GIF de personnes du bureau faisant la danse "raise the roof"