Catch up on highlights from Firebase at Google I/O 2023. Learn more

Fügen Sie Ihrer iOS-App Multi-Faktor-Authentifizierung hinzu

Wenn Sie ein Upgrade auf Firebase Authentication mit Identity Platform durchgeführt haben, können Sie Ihrer iOS-App die mehrstufige SMS-Authentifizierung hinzufügen.

Die Multi-Faktor-Authentifizierung erhöht die Sicherheit Ihrer App. Während Angreifer oft Passwörter und soziale Konten kompromittieren, ist das Abfangen einer Textnachricht schwieriger.

Bevor Sie beginnen

  1. Aktivieren Sie mindestens einen Anbieter, der die mehrstufige Authentifizierung unterstützt. Jeder Anbieter unterstützt MFA, außer Telefonauthentifizierung, anonyme Authentifizierung und Apple Game Center.

  2. Stellen Sie sicher, dass Ihre App Benutzer-E-Mails überprüft. MFA erfordert eine E-Mail-Bestätigung. Dies verhindert, dass böswillige Akteure sich mit einer E-Mail-Adresse, die ihnen nicht gehört, für einen Dienst registrieren und dann den wahren Eigentümer aussperren, indem sie einen zweiten Faktor hinzufügen.

Multi-Faktor-Authentifizierung aktivieren

  1. Öffnen Sie die Seite Authentifizierung > Anmeldemethode der Firebase- Konsole.

  2. Aktivieren Sie im Abschnitt „ Erweitert “ die SMS-Multi-Faktor-Authentifizierung .

    Sie sollten auch die Telefonnummern eingeben, mit denen Sie Ihre App testen werden. Obwohl optional, wird die Registrierung von Testtelefonnummern dringend empfohlen, um eine Drosselung während der Entwicklung zu vermeiden.

  3. Wenn Sie die Domäne Ihrer App noch nicht autorisiert haben, fügen Sie sie der Zulassungsliste auf der Seite Authentifizierung > Einstellungen der Firebase-Konsole hinzu.

Überprüfung Ihrer App

Firebase muss überprüfen, ob SMS-Anfragen von Ihrer App stammen. Sie können dies auf zwei Arten tun:

  • Stille APNs-Benachrichtigungen : Wenn Sie einen Benutzer zum ersten Mal anmelden, kann Firebase eine stille Push-Benachrichtigung an das Gerät des Benutzers senden. Die Authentifizierung kann fortgesetzt werden, wenn die App die Benachrichtigung erhält. Beachten Sie, dass Sie ab iOS 8.0 den Benutzer nicht bitten müssen, Push-Benachrichtigungen zuzulassen, um diese Methode zu verwenden.

  • reCAPTCHA-Überprüfung : Wenn Sie keine stille Benachrichtigung senden können (z. B. weil der Benutzer die Hintergrundaktualisierung deaktiviert hat oder Sie Ihre App im iOS-Simulator testen), können Sie reCAPTCHA verwenden. In vielen Fällen löst sich das reCAPTCHA automatisch ohne Benutzerinteraktion.

Verwenden von stillen Benachrichtigungen

So aktivieren Sie APNs-Benachrichtigungen für die Verwendung mit Firebase:

  1. Aktivieren Sie in Xcode Push-Benachrichtigungen für Ihr Projekt.

  2. Laden Sie Ihren APNs-Authentifizierungsschlüssel über die Firebase-Konsole hoch (Ihre Änderungen werden automatisch auf Google Cloud Firebase übertragen). Wenn Sie Ihren APNs-Authentifizierungsschlüssel noch nicht haben, erfahren Sie unter Konfigurieren von APNs mit FCM , wie Sie ihn erhalten.

    1. Öffnen Sie die Firebase-Konsole .

    2. Navigieren Sie zu Projekteinstellungen .

    3. Wählen Sie die Registerkarte Cloud-Messaging aus.

    4. Klicken Sie unter APNs-Authentifizierungsschlüssel im Konfigurationsabschnitt der iOS-App auf Hochladen .

    5. Wählen Sie Ihren Schlüssel aus.

    6. Fügen Sie die Schlüssel-ID für den Schlüssel hinzu. Die Schlüssel-ID finden Sie im Apple Developer Member Center unter Certificates, Identifiers & Profiles .

    7. Klicken Sie auf Hochladen .

Wenn Sie bereits über ein APNs-Zertifikat verfügen, können Sie stattdessen das Zertifikat hochladen.

Verwendung der reCAPTCHA-Überprüfung

So aktivieren Sie das Client-SDK zur Verwendung von reCAPTCHA:

  1. Öffnen Sie Ihre Projektkonfiguration in Xcode.

  2. Doppelklicken Sie in der linken Baumansicht auf den Projektnamen.

  3. Wählen Sie Ihre App aus dem Abschnitt „ Ziele “ aus.

  4. Wählen Sie die Registerkarte Info .

  5. Erweitern Sie den Abschnitt URL-Typen .

  6. Klicken Sie auf die Schaltfläche + .

  7. Geben Sie Ihre umgekehrte Client-ID in das Feld URL-Schemata ein. Sie finden diesen Wert in der Konfigurationsdatei GoogleService-Info.plist als REVERSED_CLIENT_ID .

Wenn Sie fertig sind, sollte Ihre Konfiguration etwa so aussehen:

Benutzerdefinierte Schemata

Optional können Sie die Art und Weise anpassen, wie Ihre App den SFSafariViewController oder UIWebView , wenn das reCAPTCHA angezeigt wird. Erstellen Sie dazu eine benutzerdefinierte Klasse, die dem FIRAuthUIDelegate Protokoll entspricht, und übergeben Sie sie an verifyPhoneNumber:UIDelegate:completion: .

Auswählen eines Registrierungsmusters

Sie können wählen, ob Ihre App eine mehrstufige Authentifizierung erfordert und wie und wann Sie Ihre Benutzer registrieren. Einige gängige Muster sind:

  • Registrieren Sie den zweiten Faktor des Benutzers als Teil der Registrierung. Verwenden Sie diese Methode, wenn Ihre App eine mehrstufige Authentifizierung für alle Benutzer erfordert. Beachten Sie, dass ein Konto über eine verifizierte E-Mail-Adresse verfügen muss, um einen zweiten Faktor zu registrieren, sodass Ihr Registrierungsablauf dies berücksichtigen muss.

  • Bieten Sie eine überspringbare Option an, um während der Registrierung einen zweiten Faktor zu registrieren. Apps, die die mehrstufige Authentifizierung fördern, aber nicht verlangen möchten, bevorzugen möglicherweise diesen Ansatz.

  • Bieten Sie die Möglichkeit, einen zweiten Faktor von der Konto- oder Profilverwaltungsseite des Benutzers anstelle des Anmeldebildschirms hinzuzufügen. Dies minimiert Reibungsverluste während des Registrierungsprozesses und stellt gleichzeitig die Multi-Faktor-Authentifizierung für sicherheitssensible Benutzer zur Verfügung.

  • Erfordern Sie das schrittweise Hinzufügen eines zweiten Faktors, wenn der Benutzer auf Funktionen mit erhöhten Sicherheitsanforderungen zugreifen möchte.

Registrierung eines zweiten Faktors

So registrieren Sie einen neuen sekundären Faktor für einen Benutzer:

  1. Authentifizieren Sie den Benutzer erneut.

  2. Bitten Sie den Benutzer, seine Telefonnummer einzugeben.

  3. Holen Sie sich eine Multi-Faktor-Sitzung für den Benutzer:

    Schnell

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

    Ziel c

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. Senden Sie eine Bestätigungsnachricht an das Telefon des Benutzers. Stellen Sie sicher, dass die Telefonnummer mit einem führenden + und ohne andere Satzzeichen oder Leerzeichen formatiert ist (z. B.: +15105551234 )

    Schnell

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

    Ziel 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.
    }];
    

    Obwohl dies nicht erforderlich ist, empfiehlt es sich, Benutzer im Voraus darüber zu informieren, dass sie eine SMS-Nachricht erhalten und dass Standardtarife gelten.

    Die Methode verifyPhoneNumber() startet den App-Überprüfungsprozess im Hintergrund mit stiller Push-Benachrichtigung. Wenn keine stille Push-Benachrichtigung verfügbar ist, wird stattdessen eine reCAPTCHA-Aufforderung ausgegeben.

  5. Sobald der SMS-Code gesendet wurde, bitten Sie den Benutzer, den Code zu bestätigen. Verwenden Sie dann ihre Antwort, um ein PhoneAuthCredential zu erstellen:

    Schnell

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

    Ziel c

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider
                                           credentialWithVerificationID:verificationID
                                           verificationCode:kPhoneSecondFactorVerificationCode];
    
  6. Initialisieren Sie ein Assertion-Objekt:

    Schnell

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Ziel c

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. Schließen Sie die Registrierung ab. Optional können Sie einen Anzeigenamen für den zweiten Faktor angeben. Dies ist nützlich für Benutzer mit mehreren Sekundenfaktoren, da die Telefonnummer während des Authentifizierungsflusses maskiert wird (z. B. +1******1234).

    Schnell

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

    Ziel 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) {
        // ...
    }];
    

Der folgende Code zeigt ein vollständiges Beispiel für die Registrierung eines zweiten Faktors:

Schnell

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
      // ...
    }
  }
})

Ziel 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) {
            // ...
        }];
    }];
}];

Glückwünsche! Sie haben erfolgreich einen zweiten Authentifizierungsfaktor für einen Benutzer registriert.

Anmelden von Benutzern mit einem zweiten Faktor

So melden Sie einen Benutzer mit Zwei-Faktor-SMS-Bestätigung an:

  1. Melden Sie den Benutzer mit seinem ersten Faktor an und fangen Sie dann einen Fehler ab, der angibt, dass eine mehrstufige Authentifizierung erforderlich ist. Dieser Fehler enthält einen Resolver, Hinweise auf die registrierten zweiten Faktoren und eine zugrunde liegende Sitzung, die beweist, dass sich der Benutzer erfolgreich mit dem ersten Faktor authentifiziert hat.

    Wenn der erste Faktor des Benutzers beispielsweise eine E-Mail-Adresse und ein Passwort war:

    Schnell

    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.
      }
    }
    

    Ziel 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.
        }
    }];
    

    Wenn der erste Faktor des Benutzers ein Verbundanbieter wie OAuth ist, fangen Sie den Fehler nach dem Aufrufen getCredentialWith() .

  2. Wenn der Benutzer mehrere sekundäre Faktoren registriert hat, fragen Sie ihn, welchen er verwenden soll. Die maskierte Telefonnummer erhalten Sie mit resolver.hints[selectedIndex].phoneNumber und den Anzeigenamen mit resolver.hints[selectedIndex].displayName .

    Schnell

    // 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.
    }
    

    Ziel 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. Senden Sie eine Bestätigungsnachricht an das Telefon des Benutzers:

    Schnell

    // 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.
    }
    

    Ziel 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. Sobald der SMS-Code gesendet wurde, bitten Sie den Benutzer, den Code zu überprüfen und ihn zum Erstellen eines PhoneAuthCredential zu verwenden:

    Schnell

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

    Ziel c

    // Ask user for the SMS verification code. Then:
    FIRPhoneAuthCredential *credential =
        [FIRPhoneAuthProvider.provider
          credentialWithVerificationID:verificationID
                      verificationCode:verificationCodeFromUser];
    
  5. Initialisieren Sie ein Assertion-Objekt mit den Anmeldeinformationen:

    Schnell

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Ziel c

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. Lösen Sie die Anmeldung auf. Sie können dann auf das ursprüngliche Anmeldeergebnis zugreifen, das die standardmäßigen anbieterspezifischen Daten und Authentifizierungsdaten enthält:

    Schnell

    // 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.
    }
    

    Ziel 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.
        }
    }];
    

Der folgende Code zeigt ein vollständiges Beispiel für die Anmeldung eines Multi-Factor-Benutzers:

Schnell

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.
        }
      }
    }
  }
}

Ziel 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.
                }
            }];
        }];
    }
}];

Glückwünsche! Sie haben einen Benutzer erfolgreich mit Multi-Faktor-Authentifizierung angemeldet.

Was kommt als nächstes