Google is committed to advancing racial equity for Black communities. See how.
Cette page a été traduite par l'API Cloud Translation.
Switch to English

Lier plusieurs fournisseurs d'authentification à un compte sur iOS

Vous pouvez autoriser les utilisateurs à se connecter à votre application à l'aide de plusieurs fournisseurs d'authentification en liant les informations d'identification du fournisseur d'authentification à un compte d'utilisateur existant. Les utilisateurs sont identifiables par le même ID utilisateur Firebase, quel que soit le fournisseur d'authentification utilisé pour se connecter. Par exemple, un utilisateur qui s'est connecté avec un mot de passe peut associer un compte Google et se connecter avec l'une ou l'autre des méthodes à l'avenir. Ou, un utilisateur anonyme peut lier un compte Facebook, puis, plus tard, se connecter avec Facebook pour continuer à utiliser votre application.

Avant que tu commences

Ajoutez la prise en charge de deux fournisseurs d'authentification ou plus (y compris éventuellement une authentification anonyme) à votre application.

Pour lier les informations d'identification du fournisseur d'authentification à un compte d'utilisateur existant:

  1. Connectez-vous l'utilisateur à l'aide de n'importe quel fournisseur ou méthode d'authentification.
  2. Terminez le flux de connexion pour le nouveau fournisseur d'authentification jusqu'à, mais non compris, en appelant l'une des méthodes FIRAuth.signInWith . Par exemple, obtenez le jeton d'identification Google de l'utilisateur, le jeton d'accès Facebook ou l'adresse e-mail et le mot de passe.
  3. Obtenez un FIRAuthCredential pour le nouveau fournisseur d'authentification:

    Connexion à Google
    Rapide
    guard let authentication = user.authentication else { return }
    let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                      accessToken: authentication.accessToken)
    
    Objectif c
    GIDAuthentication *authentication = user.authentication;
    FIRAuthCredential *credential =
    [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken
                                     accessToken:authentication.accessToken];
    
    Identifiant Facebook
    Rapide
    let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
    
    Objectif c
    FIRAuthCredential *credential = [FIRFacebookAuthProvider
        credentialWithAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
    
    Connexion par e-mail et mot de passe
    Rapide
    let credential = EmailAuthProvider.credential(withEmail: email, password: password)
    
    Objectif c
    FIRAuthCredential *credential =
        [FIREmailAuthProvider credentialWithEmail:email
                                                 password:password];
    
  4. FIRAuthCredential objet FIRAuthCredential à la méthode linkWithCredential:completion: utilisateur linkWithCredential:completion: :

    Rapide
        user.link(with: credential) { (authResult, error) in
      // ...
    }
    }
    
    Objectif c
        [[FIRAuth auth].currentUser linkWithCredential:credential
        completion:^(FIRAuthDataResult *result, NSError *_Nullable error) {
      // ...
    }];
    

    L'appel à linkWithCredential:completion: échouera si les informations d'identification sont déjà liées à un autre compte utilisateur. Dans cette situation, vous devez gérer la fusion des comptes et des données associées en fonction de votre application:

    Rapide

    let prevUser = Auth.auth().currentUser
    Auth.auth().signIn(with: credential) { (authResult, error) in
      if let error = error {
        let authError = error as NSError
        if (isMFAEnabled && authError.code == AuthErrorCode.secondFactorRequired.rawValue) {
          // The user is a multi-factor user. Second factor challenge is required.
          let resolver = authError.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
          var displayNameString = ""
          for tmpFactorInfo in (resolver.hints) {
            displayNameString += tmpFactorInfo.displayName ?? ""
            displayNameString += " "
          }
          self.showTextInputPrompt(withMessage: "Select factor to sign in\n\(displayNameString)", completionBlock: { userPressedOK, displayName in
            var selectedHint: PhoneMultiFactorInfo?
            for tmpFactorInfo in resolver.hints {
              if (displayName == tmpFactorInfo.displayName) {
                selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
              }
            }
            PhoneAuthProvider.provider().verifyPhoneNumber(with: selectedHint!, uiDelegate: nil, multiFactorSession: resolver.session) { verificationID, error in
              if error != nil {
                print("Multi factor start sign in failed. Error: \(error.debugDescription)")
              } else {
                self.showTextInputPrompt(withMessage: "Verification code for \(selectedHint?.displayName ?? "")", completionBlock: { userPressedOK, verificationCode in
                  let credential: PhoneAuthCredential? = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!, verificationCode: verificationCode!)
                  let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator.assertion(with: credential!)
                  resolver.resolveSignIn(with: assertion!) { authResult, error in
                    if error != nil {
                      print("Multi factor finanlize sign in failed. Error: \(error.debugDescription)")
                    } else {
                      self.navigationController?.popViewController(animated: true)
                    }
                  }
                })
              }
            }
          })
        } else {
          self.showMessagePrompt(error.localizedDescription)
          return
        }
        // ...
        return
      }
      // User is signed in
      // ...
    }
                // Merge prevUser and currentUser accounts and data
                // ...
            }
    

    Objectif c

    FIRUser *prevUser = [FIRAuth auth].currentUser;
    [[FIRAuth auth] signInWithCredential:credential
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                           NSError * _Nullable error) {
        if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
          FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
          NSMutableString *displayNameString = [NSMutableString string];
          for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
            [displayNameString appendString:tmpFactorInfo.displayName];
            [displayNameString appendString:@" "];
          }
          [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                               completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
           FIRPhoneMultiFactorInfo* selectedHint;
           for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
             if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
               selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
             }
           }
           [FIRPhoneAuthProvider.provider
            verifyPhoneNumberWithMultiFactorInfo:selectedHint
            UIDelegate:nil
            multiFactorSession:resolver.session
            completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
              if (error) {
                [self showMessagePrompt:error.localizedDescription];
              } else {
                [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                     completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
                 FIRPhoneAuthCredential *credential =
                     [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                                  verificationCode:verificationCode];
                 FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
                 [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
                   if (error) {
                     [self showMessagePrompt:error.localizedDescription];
                   } else {
                     NSLog(@"Multi factor finanlize sign in succeeded.");
                   }
                 }];
               }];
              }
            }];
         }];
        }
      else if (error) {
        // ...
        return;
      }
      // User successfully signed in. Get user data from the FIRUser object
      if (authResult == nil) { return; }
      FIRUser *user = authResult.user;
      // ...
    }];
                                        // Merge prevUser and currentUser accounts and data
                                        // ...
                                    }];
    

Si l'appel à linkWithCredential:completion: réussit, l'utilisateur peut désormais se connecter à l'aide de n'importe quel fournisseur d'authentification lié et accéder aux mêmes données Firebase.

Vous pouvez dissocier un fournisseur d'authentification d'un compte, afin que l'utilisateur ne puisse plus se connecter avec ce fournisseur.

Pour dissocier un fournisseur d'authentification d'un compte d'utilisateur, transmettez l'ID de fournisseur à la unlinkFromProvider:completion: Vous pouvez obtenir les ID de fournisseur des fournisseurs d'authentification liés à un utilisateur à partir de la propriété providerData .

Rapide

Auth.auth().currentUser?.unlink(fromProvider: providerID!) { (user, error) in
  // ...
}

Objectif c

[[FIRAuth auth].currentUser unlinkFromProvider:providerID
                                    completion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
  // ...
}];