S'authentifier avec Firebase avec un numéro de téléphone à l'aide de JavaScript

Vous pouvez utiliser Firebase Authentication pour connecter un utilisateur en lui envoyant un message SMS sur son téléphone. L'utilisateur se connecte à l'aide d'un code à usage unique contenu dans le message SMS.

Le moyen le plus simple d'ajouter la connexion par numéro de téléphone à votre application est d'utiliser FirebaseUI, qui inclut un widget de connexion intégré qui implémente les flux de connexion pour la connexion par numéro de téléphone, ainsi que la connexion par mot de passe et la connexion fédérée. Ce document explique comment implémenter un flux de connexion avec un numéro de téléphone à l'aide du SDK Firebase.

Avant de commencer

Si ce n'est pas déjà fait, copiez l'extrait d'initialisation de la console Firebase dans votre projet, comme décrit dans Ajouter Firebase à votre projet JavaScript.

Problèmes de sécurité

L'authentification à l'aide d'un numéro de téléphone uniquement, bien que pratique, est moins sécurisée que les autres méthodes disponibles, car la possession d'un numéro de téléphone peut être facilement transférée entre les utilisateurs. De plus, sur les appareils comportant plusieurs profils utilisateur, tout utilisateur pouvant recevoir des SMS peut se connecter à un compte à l'aide du numéro de téléphone de l'appareil.

Si vous utilisez la connexion par numéro de téléphone dans votre application, vous devez la proposer en plus de méthodes de connexion plus sécurisées et informer les utilisateurs des compromis de sécurité liés à l'utilisation de la connexion par numéro de téléphone.

Activer la connexion par numéro de téléphone pour votre projet Firebase

Pour connecter les utilisateurs par SMS, vous devez d'abord activer la méthode de connexion par numéro de téléphone pour votre projet Firebase :

  1. Dans la console Firebase, ouvrez la section Authentification.
  2. Sur la page Méthode de connexion, activez la méthode de connexion Numéro de téléphone.
  3. Facultatif : Sur la page Paramètres, définissez une règle concernant les régions vers lesquelles vous souhaitez autoriser ou interdire l'envoi de messages SMS. Définir une règle régionale pour les SMS peut vous aider à protéger vos applications contre l'utilisation abusive des SMS.
  4. Sur la même page, si le domaine qui hébergera votre application ne figure pas dans la section Domaines de redirection OAuth, ajoutez-le. Notez que localhost n'est pas autorisé en tant que domaine hébergé pour l'authentification par téléphone.

Configurer l'outil de vérification reCAPTCHA

Avant de pouvoir connecter des utilisateurs avec leur numéro de téléphone, vous devez configurer le vérificateur reCAPTCHA de Firebase. Firebase utilise reCAPTCHA pour éviter les abus, par exemple en s'assurant que la demande de validation du numéro de téléphone provient de l'un des domaines autorisés de votre application.

Vous n'avez pas besoin de configurer manuellement un client reCAPTCHA. Lorsque vous utilisez l'objet RecaptchaVerifier du SDK Firebase, Firebase crée et gère automatiquement les codes secrets et les clés de client nécessaires.

L'objet RecaptchaVerifier est compatible avec la méthode reCAPTCHA invisible, qui permet souvent de valider l'utilisateur sans aucune action de sa part, ainsi qu'avec le widget reCAPTCHA, qui nécessite toujours une interaction de l'utilisateur pour être complété.

Le reCAPTCHA sous-jacent peut être localisé selon les préférences de l'utilisateur en mettant à jour le code de langue sur l'instance Auth avant d'afficher le reCAPTCHA. La localisation mentionnée ci-dessus s'appliquera également au message SMS envoyé à l'utilisateur et contenant le code de validation.

Web

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

Utiliser reCAPTCHA invisible

Pour utiliser un reCAPTCHA invisible, créez un objet RecaptchaVerifier avec le paramètre size défini sur invisible, en spécifiant l'ID du bouton qui envoie votre formulaire de connexion. Exemple :

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Utiliser le widget reCAPTCHA

Pour utiliser le widget reCAPTCHA visible, créez un élément sur votre page pour contenir le widget, puis créez un objet RecaptchaVerifier en spécifiant l'ID du conteneur. Par exemple :

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

Facultatif : spécifiez les paramètres reCAPTCHA

Vous pouvez éventuellement définir des fonctions de rappel sur l'objet RecaptchaVerifier qui sont appelées lorsque l'utilisateur résout le reCAPTCHA ou lorsque le reCAPTCHA expire avant que l'utilisateur n'envoie le formulaire :

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Facultatif : préafficher la méthode reCAPTCHA

Si vous souhaitez préafficher la méthode reCAPTCHA avant d'envoyer une demande de connexion, appelez render :

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Une fois l'opération render résolue, vous obtenez l'ID de widget de la méthode reCAPTCHA, que vous pouvez utiliser pour appeler l'API reCAPTCHA :

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Envoyez un code de validation sur le téléphone de l'utilisateur.

Pour lancer la connexion par numéro de téléphone, présentez à l'utilisateur une interface qui l'invite à fournir son numéro de téléphone, puis appelez signInWithPhoneNumber pour demander à Firebase d'envoyer un code d'authentification au téléphone de l'utilisateur par SMS :

  1. Obtenez le numéro de téléphone de l'utilisateur.

    Les exigences légales varient, mais il est recommandé d'informer vos utilisateurs que s'ils utilisent la connexion par téléphone, ils peuvent recevoir un message SMS pour la validation et que les tarifs standards s'appliquent.

  2. Appelez signInWithPhoneNumber en lui transmettant le numéro de téléphone de l'utilisateur et le RecaptchaVerifier que vous avez créé précédemment.

    Web

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    Si signInWithPhoneNumber génère une erreur, réinitialisez reCAPTCHA afin que l'utilisateur puisse réessayer :
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });

La méthode signInWithPhoneNumber envoie le test reCAPTCHA à l'utilisateur. Si l'utilisateur réussit le test, elle demande à Firebase Authentication d'envoyer un message SMS contenant un code de validation sur le téléphone de l'utilisateur.

Connectez l'utilisateur avec le code de validation.

Une fois l'appel à signInWithPhoneNumber réussi, invitez l'utilisateur à saisir le code de validation qu'il a reçu par SMS. Connectez ensuite l'utilisateur en transmettant le code à la méthode confirm de l'objet ConfirmationResult qui a été transmis au gestionnaire de traitement de signInWithPhoneNumber (c'est-à-dire son bloc then). Exemple :

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Si l'appel à confirm a réussi, l'utilisateur est connecté.

Obtenir l'objet AuthCredential intermédiaire

Si vous devez obtenir un objet AuthCredential pour le compte de l'utilisateur, transmettez le code de validation du résultat de la confirmation et le code de validation à PhoneAuthProvider.credential au lieu d'appeler confirm :

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

Vous pouvez ensuite connecter l'utilisateur avec l'identifiant :

firebase.auth().signInWithCredential(credential);

Effectuer des tests avec des numéros de téléphone fictifs

Vous pouvez configurer des numéros de téléphone fictifs pour le développement via la console Firebase. Tester avec des numéros de téléphone fictifs présente les avantages suivants :

  • Testez l'authentification par numéro de téléphone sans consommer votre quota d'utilisation.
  • Testez l'authentification par numéro de téléphone sans envoyer de SMS.
  • Exécutez des tests consécutifs avec le même numéro de téléphone sans être limité. Cela minimise le risque de refus lors du processus d'examen de l'App Store si l'examinateur utilise le même numéro de téléphone pour les tests.
  • Testez facilement dans les environnements de développement sans effort supplémentaire, par exemple en développant dans un simulateur iOS ou un émulateur Android sans les services Google Play.
  • Écrivez des tests d'intégration sans être bloqué par les contrôles de sécurité normalement appliqués aux vrais numéros de téléphone dans un environnement de production.

Les numéros de téléphone fictifs doivent répondre aux exigences suivantes :

  1. Assurez-vous d'utiliser des numéros de téléphone fictifs qui n'existent pas déjà. Firebase Authentication ne vous permet pas de définir des numéros de téléphone existants utilisés par de vrais utilisateurs comme numéros de test. Vous pouvez, par exemple, utiliser des numéros de téléphone de test américains commençant par 555 : +1 650-555-3434
  2. Les numéros de téléphone doivent être correctement formatés en termes de longueur et d'autres contraintes. Ils seront toujours soumis à la même validation que les numéros de téléphone des utilisateurs réels.
  3. Vous pouvez ajouter jusqu'à 10 numéros de téléphone pour le développement.
  4. Utilisez des numéros/codes de téléphone de test difficiles à deviner et modifiez-les fréquemment.

Créer des numéros de téléphone et des codes de validation fictifs

  1. Dans la console Firebase, ouvrez la section Authentification.
  2. Dans l'onglet Méthode de connexion, activez le fournisseur de téléphone si ce n'est pas déjà fait.
  3. Ouvrez le menu accordéon Numéros de téléphone à des fins de test.
  4. Indiquez le numéro de téléphone que vous souhaitez tester, par exemple +1 650-555-3434.
  5. Indiquez le code de validation à six chiffres pour ce numéro spécifique, par exemple 654321.
  6. Ajoutez le numéro. Si nécessaire, vous pouvez supprimer le numéro de téléphone et son code en pointant sur la ligne correspondante et en cliquant sur l'icône en forme de corbeille.

Tests manuels

Vous pouvez commencer à utiliser directement un numéro de téléphone fictif dans votre application. Cela vous permet d'effectuer des tests manuels pendant les phases de développement sans rencontrer de problèmes de quota ni de limitation du débit. Vous pouvez également effectuer des tests directement à partir d'un simulateur iOS ou d'un émulateur Android sans les services Google Play.

Lorsque vous fournissez le numéro de téléphone fictif et envoyez le code de validation, aucun SMS n'est réellement envoyé. Vous devez plutôt fournir le code de validation précédemment configuré pour vous connecter.

Une fois la connexion effectuée, un utilisateur Firebase est créé avec ce numéro de téléphone. Cet utilisateur a le même comportement et les mêmes propriétés qu'un véritable utilisateur de numéro de téléphone, et peut accéder à Realtime Database/Cloud Firestore et à d'autres services de la même manière. Le jeton d'identité généré au cours de ce processus a la même signature qu'un véritable utilisateur de numéro de téléphone.

Une autre option consiste à définir un rôle de test via des revendications personnalisées pour ces utilisateurs afin de les différencier en tant que faux utilisateurs si vous souhaitez restreindre davantage l'accès.

Tests d'intégration

En plus des tests manuels, Firebase Authentication fournit des API pour vous aider à écrire des tests d'intégration pour les tests d'authentification par téléphone. Ces API désactivent la validation des applications en désactivant l'exigence reCAPTCHA sur le Web et les notifications push silencieuses dans iOS. Cela permet de tester l'automatisation dans ces flux et de la mettre en œuvre plus facilement. De plus, ils permettent de tester les flux de validation instantanée sur Android.

Sur le Web, définissez appVerificationDisabledForTesting sur true avant d'afficher firebase.auth.RecaptchaVerifier. Cela résout automatiquement le reCAPTCHA, ce qui vous permet de transmettre le numéro de téléphone sans le résoudre manuellement. Notez que même si reCAPTCHA est désactivé, vous ne pourrez toujours pas vous connecter si vous utilisez un numéro de téléphone non fictif. Seuls les numéros de téléphone fictifs peuvent être utilisés avec cette API.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

Les outils de vérification de reCAPTCHA factice visible et invisible se comportent différemment lorsque la validation des applications est désactivée :

  • reCAPTCHA visible : lorsque le reCAPTCHA visible est affiché via appVerifier.render(), il se résout automatiquement après un bref délai. Cela équivaut à un utilisateur qui clique sur reCAPTCHA immédiatement après le rendu. La réponse reCAPTCHA expirera au bout d'un certain temps, puis se résoudra à nouveau automatiquement.
  • reCAPTCHA invisible : le reCAPTCHA invisible ne se résout pas automatiquement lors du rendu, mais plutôt lors de l'appel appVerifier.verify() ou lorsque l'ancrage du bouton reCAPTCHA est cliqué après un bref délai. De même, la réponse expirera après un certain temps et ne se résoudra automatiquement qu'après l'appel appVerifier.verify() ou lorsque l'ancrage du bouton reCAPTCHA sera cliqué à nouveau.

Chaque fois qu'un mock reCAPTCHA est résolu, la fonction de rappel correspondante est déclenchée comme prévu avec la fausse réponse. Si un rappel d'expiration est également spécifié, il se déclenchera à l'expiration.

Étapes suivantes

Lorsqu'un utilisateur se connecte pour la première fois, un compte utilisateur est créé et associé aux identifiants (nom d'utilisateur et mot de passe, numéro de téléphone ou informations du fournisseur d'authentification) avec lesquels il s'est connecté. Ce nouveau compte est stocké dans votre projet Firebase et peut être utilisé pour identifier un utilisateur dans toutes les applications de votre projet, quelle que soit la méthode de connexion de l'utilisateur.

  • Dans vos applications, la méthode recommandée pour connaître l'état d'authentification de votre utilisateur consiste à définir un observateur sur l'objet Auth. Vous pouvez ensuite obtenir les informations de profil de base de l'utilisateur à partir de l'objet User. Consultez Gérer les utilisateurs.

  • Dans vos règles de sécurité Firebase Realtime Database et Cloud Storage, vous pouvez obtenir l'ID utilisateur unique de l'utilisateur connecté à partir de la variable auth et l'utiliser pour contrôler les données auxquelles un utilisateur peut accéder.

Vous pouvez autoriser les utilisateurs à se connecter à votre application à l'aide de plusieurs fournisseurs d'authentification en associant les identifiants du fournisseur d'authentification à un compte utilisateur existant.

Pour déconnecter un utilisateur, appelez signOut :

Web

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});