Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

Ajoutez l'authentification multifacteur à votre application iOS

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Si vous avez effectué la mise à niveau vers Firebase Authentication with Identity Platform, vous pouvez ajouter l'authentification multifacteur SMS à votre application iOS.

L'authentification multifacteur augmente la sécurité de votre application. Alors que les attaquants compromettent souvent les mots de passe et les comptes sociaux, l'interception d'un message texte est plus difficile.

Avant que tu commences

  1. Activez au moins un fournisseur prenant en charge l'authentification multifacteur. Chaque fournisseur prend en charge MFA, à l' exception de l'authentification par téléphone, de l'authentification anonyme et d'Apple Game Center.

  2. Assurez-vous que votre application vérifie les e-mails des utilisateurs. MFA nécessite une vérification par e-mail. Cela empêche les acteurs malveillants de s'inscrire à un service avec un e-mail qu'ils ne possèdent pas, puis de verrouiller le véritable propriétaire en ajoutant un deuxième facteur.

Activer l'authentification multifacteur

  1. Ouvrez la page Authentification > Méthode de connexion de la console Firebase.

  2. Dans la section Avancé , activez Authentification multifacteur SMS .

    Vous devez également entrer les numéros de téléphone avec lesquels vous testerez votre application. Bien que facultatif, l'enregistrement des numéros de téléphone de test est fortement recommandé pour éviter les limitations pendant le développement.

  3. Si vous n'avez pas encore autorisé le domaine de votre application, ajoutez-le à la liste verte sur la page Authentification > Paramètres de la console Firebase.

Vérification de votre application

Firebase doit vérifier que les requêtes SMS proviennent de votre application. Vous pouvez le faire de deux manières :

  • Notifications APN silencieuses : lorsque vous connectez un utilisateur pour la première fois, Firebase peut envoyer une notification push silencieuse à l'appareil de l'utilisateur. L'authentification peut continuer si l'application reçoit la notification. Notez qu'à partir d'iOS 8.0, vous n'avez pas besoin de demander à l'utilisateur d'autoriser les notifications push pour utiliser cette méthode.

  • Vérification reCAPTCHA : si vous ne pouvez pas envoyer de notification silencieuse (par exemple, parce que l'utilisateur a désactivé l'actualisation en arrière-plan ou que vous testez votre application dans le simulateur iOS), vous pouvez utiliser reCAPTCHA. Dans de nombreux cas, le reCAPTCHA se résoudra automatiquement sans interaction de l'utilisateur.

Utilisation des notifications silencieuses

Pour activer les notifications APN à utiliser avec Firebase :

  1. Dans Xcode, activez les notifications push pour votre projet.

  2. Téléchargez votre clé d'authentification APNs à l'aide de la console Firebase (vos modifications seront automatiquement répercutées sur Google Cloud Firebase). Si vous n'avez pas encore votre clé d'authentification APNs, consultez Configuration des APNs avec FCM pour savoir comment l'obtenir.

    1. Ouvrez la console Firebase .

    2. Accédez aux paramètres du projet .

    3. Sélectionnez l'onglet Messagerie Cloud .

    4. Sous Clé d' authentification APNs , dans la section de configuration de l'application iOS , cliquez sur Charger .

    5. Sélectionnez votre clé.

    6. Ajoutez l'ID de clé pour la clé. Vous pouvez trouver l'ID de clé sous Certificats, identifiants et profils dans l' Apple Developer Member Center .

    7. Cliquez sur Télécharger .

Si vous avez déjà un certificat APNs, vous pouvez le télécharger à la place.

Utilisation de la vérification reCAPTCHA

Pour permettre au SDK client d'utiliser reCAPTCHA :

  1. Ouvrez la configuration de votre projet dans Xcode.

  2. Double-cliquez sur le nom du projet dans l'arborescence de gauche.

  3. Sélectionnez votre application dans la section Cibles .

  4. Sélectionnez l'onglet Infos .

  5. Développez la section Types d'URL .

  6. Cliquez sur le bouton + .

  7. Saisissez votre ID client inversé dans le champ Schémas d'URL . Vous pouvez trouver cette valeur répertoriée dans le fichier de configuration GoogleService-Info.plist sous la forme REVERSED_CLIENT_ID .

Une fois terminée, votre configuration devrait ressembler à ce qui suit :

Schémas personnalisés

En option, vous pouvez personnaliser la façon dont votre application présente le SFSafariViewController ou UIWebView lors de l'affichage du reCAPTCHA. Pour ce faire, créez une classe personnalisée conforme au protocole FIRAuthUIDelegate et transmettez-la à verifyPhoneNumber:UIDelegate:completion: .

Choisir un modèle d'inscription

Vous pouvez choisir si votre application requiert une authentification multifacteur, et comment et quand inscrire vos utilisateurs. Certains modèles courants incluent :

  • Inscrivez le deuxième facteur de l'utilisateur dans le cadre de l'inscription. Utilisez cette méthode si votre application nécessite une authentification multifacteur pour tous les utilisateurs. Notez qu'un compte doit avoir une adresse e-mail vérifiée pour inscrire un deuxième facteur, votre processus d'inscription devra donc en tenir compte.

  • Offrez une option désactivable pour inscrire un deuxième facteur lors de l'inscription. Les applications qui souhaitent encourager, mais pas exiger, l'authentification multifacteur peuvent préférer cette approche.

  • Offrez la possibilité d'ajouter un deuxième facteur à partir de la page de gestion du compte ou du profil de l'utilisateur, au lieu de l'écran d'inscription. Cela minimise les frictions pendant le processus d'inscription, tout en rendant l'authentification multifacteur disponible pour les utilisateurs sensibles à la sécurité.

  • Nécessite l'ajout progressif d'un deuxième facteur lorsque l'utilisateur souhaite accéder à des fonctionnalités avec des exigences de sécurité accrues.

Inscrire un deuxième facteur

Pour inscrire un nouveau facteur secondaire pour un utilisateur :

  1. Réauthentifiez l'utilisateur.

  2. Demandez à l'utilisateur d'entrer son numéro de téléphone.

  3. Obtenez une session multi-facteurs pour l'utilisateur :

    Rapide

    authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in
      // ...
    }
    

    Objectif c

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. Envoyez un message de vérification au téléphone de l'utilisateur. Assurez-vous que le numéro de téléphone est formaté avec un signe + et aucun autre signe de ponctuation ou espace blanc (par exemple : +15105551234 )

    Rapide

    // Send SMS verification code.
    PhoneAuthProvider.provider().verifyPhoneNumber(
      phoneNumber,
      uiDelegate: nil,
      multiFactorSession: session) { (verificationId, error) in
        // verificationId will be needed for enrollment completion.
    }
    

    Objectif c

    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber
                                          UIDelegate:nil
                                  multiFactorSession:session
                                          completion:^(NSString * _Nullable verificationID,
                                                        NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.
    }];
    

    Bien que cela ne soit pas obligatoire, il est recommandé d'informer les utilisateurs à l'avance qu'ils recevront un SMS et que les tarifs standard s'appliquent.

    La méthode verifyPhoneNumber() démarre le processus de vérification de l'application en arrière-plan à l'aide d'une notification push silencieuse. Si la notification push silencieuse n'est pas disponible, un défi reCAPTCHA est émis à la place.

  5. Une fois le code SMS envoyé, demandez à l'utilisateur de vérifier le code. Ensuite, utilisez leur réponse pour créer un PhoneAuthCredential :

    Rapide

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId,
      verificationCode: verificationCode)
    

    Objectif c

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider
                                           credentialWithVerificationID:verificationID
                                           verificationCode:kPhoneSecondFactorVerificationCode];
    
  6. Initialisez un objet d'assertion :

    Rapide

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objectif c

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. Complétez l'inscription. Si vous le souhaitez, vous pouvez spécifier un nom d'affichage pour le deuxième facteur. Ceci est utile pour les utilisateurs avec plusieurs seconds facteurs, car le numéro de téléphone est masqué pendant le flux d'authentification (par exemple, +1******1234).

    Rapide

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
    

    Objectif c

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    [authResult.user.multiFactor enrollWithAssertion:assertion
                                         displayName:nil
                                          completion:^(NSError * _Nullable error) {
        // ...
    }];
    

Le code ci-dessous montre un exemple complet d'inscription d'un deuxième facteur :

Rapide

let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
  // Send SMS verification code.
  PhoneAuthProvider.provider().verifyPhoneNumber(
    phoneNumber,
    uiDelegate: nil,
    multiFactorSession: session
  ) { (verificationId, error) in
    // verificationId will be needed for enrollment completion.
    // Ask user for the verification code.
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: phoneSecondFactorVerificationCode)
    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
      // ...
    }
  }
})

Objectif c

FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                              NSError * _Nullable error) {
    // Send SMS verification code.
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumber:phoneNumber
      UIDelegate:nil
      multiFactorSession:session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        // verificationId will be needed for enrollment completion.

        // Ask user for the verification code.
        // ...

        // Then:
        FIRPhoneAuthCredential *credential =
            [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
                                                        verificationCode:kPhoneSecondFactorVerificationCode];
        FIRMultiFactorAssertion *assertion =
            [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

        // Complete enrollment. This will update the underlying tokens
        // and trigger ID token change listener.
        [user.multiFactor enrollWithAssertion:assertion
                                  displayName:displayName
                                    completion:^(NSError * _Nullable error) {
            // ...
        }];
    }];
}];

Toutes nos félicitations! Vous avez enregistré avec succès un deuxième facteur d'authentification pour un utilisateur.

Connexion des utilisateurs avec un deuxième facteur

Pour connecter un utilisateur avec la vérification par SMS à deux facteurs :

  1. Connectez l'utilisateur avec son premier facteur, puis détectez une erreur indiquant qu'une authentification multifacteur est requise. Cette erreur contient un résolveur, des indices sur les seconds facteurs inscrits et une session sous-jacente prouvant que l'utilisateur s'est authentifié avec succès avec le premier facteur.

    Par exemple, si le premier facteur de l'utilisateur était une adresse e-mail et un mot de passe :

    Rapide

    Auth.auth().signIn(
      withEmail: email,
      password: password
    ) { (result, error) in
      let authError = error as NSError
      if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
        // The user is a multi-factor user. Second factor challenge is required.
        let resolver =
          authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
        // ...
      } else {
        // Handle other errors such as wrong password.
      }
    }
    

    Objectif c

    [FIRAuth.auth signInWithEmail:email
                         password:password
                       completion:^(FIRAuthDataResult * _Nullable authResult,
                                    NSError * _Nullable error) {
        if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
            // User is not enrolled with a second factor and is successfully signed in.
            // ...
        } else {
            // The user is a multi-factor user. Second factor challenge is required.
        }
    }];
    

    Si le premier facteur de l'utilisateur est un fournisseur fédéré, tel que OAuth, interceptez l'erreur après avoir appelé getCredentialWith() .

  2. Si l'utilisateur a inscrit plusieurs facteurs secondaires, demandez-lui lequel utiliser. Vous pouvez obtenir le numéro de téléphone masqué avec resolver.hints[selectedIndex].phoneNumber et le nom d'affichage avec resolver.hints[selectedIndex].displayName .

    Rapide

    // Ask user which second factor to use. Then:
    if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID {
      // User selected a phone second factor.
      // ...
    } else {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    

    Objectif c

    FIRMultiFactorResolver *resolver =
        (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
    
    // Ask user which second factor to use. Then:
    FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
    if (hint.factorID == FIRPhoneMultiFactorID) {
      // User selected a phone second factor.
      // ...
    } else {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    
  3. Envoyez un message de vérification au téléphone de l'utilisateur :

    Rapide

    // Send SMS verification code.
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      // verificationId will be needed for sign-in completion.
    }
    

    Objectif c

    // Send SMS verification code
    [FIRPhoneAuthProvider.provider
      verifyPhoneNumberWithMultiFactorInfo:hint
      UIDelegate:nil
      multiFactorSession:resolver.session
      completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
        if (error != nil) {
            // Failed to verify phone number.
        }
    }];
    
  4. Une fois le code SMS envoyé, demandez à l'utilisateur de vérifier le code et de l'utiliser pour créer un PhoneAuthCredential :

    Rapide

    // Ask user for the verification code. Then:
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId!,
      verificationCode: verificationCodeFromUser)
    

    Objectif c

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential =
        [FIRPhoneAuthProvider.provider
          credentialWithVerificationID:verificationID
                      verificationCode:verificationCodeFromUser];
    
  5. Initialisez un objet d'assertion avec les informations d'identification :

    Rapide

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objectif c

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. Résolvez la connexion. Vous pouvez ensuite accéder au résultat de connexion d'origine, qui inclut les données standard spécifiques au fournisseur et les identifiants d'authentification :

    Rapide

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(with: assertion) { (authResult, error) in
      // authResult will also contain the user, additionalUserInfo, optional
      // credential (null for email/password) associated with the first factor sign-in.
    
      // For example, if the user signed in with Google as a first factor,
      // authResult.additionalUserInfo will contain data related to Google provider that
      // the user signed in with.
    
      // user.credential contains the Google OAuth credential.
      // user.credential.accessToken contains the Google OAuth access token.
      // user.credential.idToken contains the Google OAuth ID token.
    }
    

    Objectif c

    // Complete sign-in.
    [resolver resolveSignInWithAssertion:assertion
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                            NSError * _Nullable error) {
        if (error != nil) {
            // User successfully signed in with the second factor phone number.
        }
    }];
    

Le code ci-dessous montre un exemple complet de connexion d'un utilisateur multifacteur :

Rapide

Auth.auth().signIn(
  withEmail: email,
  password: password
) { (result, error) in
  let authError = error as NSError?
  if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
    let resolver =
      authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver

    // Ask user which second factor to use.
    // ...

    // Then:
    let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo

    // Send SMS verification code
    PhoneAuthProvider.provider().verifyPhoneNumber(
      with: hint,
      uiDelegate: nil,
      multiFactorSession: resolver.session
    ) { (verificationId, error) in
      if error != nil {
        // Failed to verify phone number.
      }
      // Ask user for the SMS verification code.
      // ...

      // Then:
      let credential = PhoneAuthProvider.provider().credential(
        withVerificationID: verificationId!,
        verificationCode: verificationCodeFromUser)
      let assertion = PhoneMultiFactorGenerator.assertion(with: credential)

      // Complete sign-in.
      resolver.resolveSignIn(with: assertion) { (authResult, error) in
        if error != nil {
          // User successfully signed in with the second factor phone number.
        }
      }
    }
  }
}

Objectif c

[FIRAuth.auth signInWithEmail:email
                     password:password
                   completion:^(FIRAuthDataResult * _Nullable authResult,
                               NSError * _Nullable error) {
    if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
        // User is not enrolled with a second factor and is successfully signed in.
        // ...
    } else {
        FIRMultiFactorResolver *resolver =
            (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];

        // Ask user which second factor to use.
        // ...

        // Then:
        FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];

        // Send SMS verification code
        [FIRPhoneAuthProvider.provider
          verifyPhoneNumberWithMultiFactorInfo:hint
                                    UIDelegate:nil
                            multiFactorSession:resolver.session
                                    completion:^(NSString * _Nullable verificationID,
                                                NSError * _Nullable error) {
            if (error != nil) {
                // Failed to verify phone number.
            }

            // Ask user for the SMS verification code.
            // ...

            // Then:
            FIRPhoneAuthCredential *credential =
                [FIRPhoneAuthProvider.provider
                  credentialWithVerificationID:verificationID
                              verificationCode:kPhoneSecondFactorVerificationCode];
            FIRMultiFactorAssertion *assertion =
                [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];

            // Complete sign-in.
            [resolver resolveSignInWithAssertion:assertion
                                      completion:^(FIRAuthDataResult * _Nullable authResult,
                                                    NSError * _Nullable error) {
                if (error != nil) {
                    // User successfully signed in with the second factor phone number.
                }
            }];
        }];
    }
}];

Toutes nos félicitations! Vous avez réussi à connecter un utilisateur à l'aide de l'authentification multifacteur.

Et après