Multi-Faktor-Authentifizierung zu Ihrer iOS-App hinzufügen

Wenn Sie ein Upgrade auf Firebase Authentication with Identity Platform ausgeführt haben, können Sie die Multi-Faktor-Authentifizierung per SMS hinzufügen in Ihrer iOS-App.

Die Multi-Faktor-Authentifizierung erhöht die Sicherheit Ihrer Anwendung. Während Angreifer häufig Passwörter und Konten bei sozialen Netzwerken missbrauchen, ist das Abfangen einer SMS schwieriger.

Hinweis

  1. Aktivieren Sie mindestens einen Anbieter, der die Multi-Faktor-Authentifizierung unterstützt. Alle Anbieter unterstützen MFA, außer der Authentifizierung per Telefon, der anonymen Authentifizierung Apple Game Center.

  2. Achten Sie darauf, dass die Anwendung die E-Mail-Adressen der Nutzer überprüft. Die Multi-Faktor-Authentifizierung erfordert eine E-Mail-Bestätigung. So wird verhindert, dass sich böswillige Akteure bei einem Dienst mit einer E-Mail-Adresse registrieren, die ihnen nicht gehört, und dann den echten Inhaber sperren, 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 Option Multi-Faktor-Authentifizierung per SMS.

    Sie sollten auch die Telefonnummern eingeben, mit denen Sie Ihre App testen möchten. Die Registrierung von Testtelefonnummern ist zwar optional, wird aber dringend empfohlen, eine Drosselung während der Entwicklung zu vermeiden.

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

Anwendung prüfen

Firebase muss überprüfen, ob SMS-Anfragen von Ihrem Dazu haben Sie zwei Möglichkeiten:

  • Lautlose APNs-Benachrichtigungen: Wenn Sie einen Nutzer zum ersten Mal anmelden, kann Firebase eine lautlose Push-Benachrichtigung an das Gerät des Nutzers senden. Die Authentifizierung kann fortgesetzt werden, wenn die App die Benachrichtigung erhält. Ab iOS 8.0 müssen Sie den Nutzer nicht bitten, die Push-Benachrichtigungen für diese Methode zu verwenden.

  • reCAPTCHA-Verifizierung: Wenn Sie keine unregelmäßige Benachrichtigung senden können, z. B. weil der Nutzer die Hintergrundaktualisierung deaktiviert oder Ihre App im iOS-Simulator getestet hat, können Sie reCAPTCHA verwenden. In vielen Fällen löst sich reCAPTCHA automatisch ohne Nutzerinteraktion.

Stumme Benachrichtigungen verwenden

So aktivieren Sie APNs-Benachrichtigungen zur Verwendung mit Firebase:

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

  2. Laden Sie Ihren APN-Authentifizierungsschlüssel über die Firebase Console hoch. Ihre Änderungen werden automatisch auf Google Cloud Firebase übertragen. Wenn Sie noch keinen APN-Authentifizierungsschlüssel haben, lesen Sie die Informationen unter APNs mit FCM konfigurieren, um ihn zu erhalten.

    1. Öffnen Sie die Firebase Console.

    2. Gehen Sie zu Projekteinstellungen.

    3. Wählen Sie den Tab Cloud Messaging aus.

    4. Klicken Sie unter APNs-Authentifizierungsschlüssel im Abschnitt Konfiguration 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. Sie finden die Schlüssel-ID unter Zertifikate, Kennungen und Profile im Apple Developer Member Center.

    7. Klicken Sie auf Hochladen.

Wenn Sie bereits ein APNs-Zertifikat haben, können Sie stattdessen das Zertifikat hochladen.

reCAPTCHA-Verifizierung verwenden

So aktivieren Sie das Client-SDK für die Verwendung von reCAPTCHA:

  1. Öffnen Sie Ihre Projektkonfiguration in Xcode.

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

  3. Wählen Sie im Bereich Ziele Ihre App aus.

  4. Wähle den Tab Info aus.

  5. Maximieren Sie den Bereich URL-Typen.

  6. Klicken Sie auf die Schaltfläche +.

  7. Geben Sie Ihre Client-ID in umgekehrter Reihenfolge in das Feld URL-Schemas ein. Sie finden diesen Wert in der Konfigurationsdatei GoogleService-Info.plist als REVERSED_CLIENT_ID gelistet.

Ihre Konfiguration sollte anschließend in etwa so aussehen:

Benutzerdefinierte Schemas

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

Registrierungsmuster auswählen

Sie können auswählen, ob Ihre Anwendung eine Multi-Faktor-Authentifizierung erfordert, und wie und wann Ihre Nutzer registriert werden sollen. Hier einige gängige Muster:

  • Bieten Sie den zweiten Faktor des Nutzers als Teil der Registrierung an. Verwenden Sie diese Methode, wenn Ihre Anwendung eine Multi-Faktor-Authentifizierung für alle Nutzer erfordert. Für die Registrierung eines zweiten Faktors muss ein Konto eine bestätigte E-Mail-Adresse haben. Dies muss bei der Registrierung berücksichtigt werden.

  • Bieten Sie bei der Registrierung eine überspringbare Option an, mit der ein zweiter Faktor registriert werden kann. Anwendungen, die zwar zur Multi-Faktor-Authentifizierung ermutigen möchten, diese aber nicht erfordern, bevorzugen möglicherweise diesen Ansatz.

  • Ermöglichen Sie, dass ein zweiter Faktor über die Konto- oder Profilverwaltungsseite des Nutzers hinzufügbar ist anstelle über den Anmeldebildschirm. Dadurch wird der Registrierungsprozess vereinfacht und gleichzeitig die Multi-Faktor-Authentifizierung für sicherheitsorientierte Nutzer verfügbar gemacht.

  • Das Hinzufügen eines zweiten Faktors ist erforderlich, wenn der Nutzer auf Features mit höheren Sicherheitsanforderungen zugreifen möchte.

Zweiten Faktor registrieren

So registrieren Sie einen neuen zweiten Faktor für einen Nutzer:

  1. Authentifizieren Sie den Nutzer noch einmal.

  2. Fordern Sie den Nutzer zur Eingabe seiner Telefonnummer auf.

  3. Starten Sie eine Multi-Faktor-Sitzung für den Nutzer:

    Swift

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

    Objective-C

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. Senden Sie eine Bestätigungsnachricht an das Mobiltelefon des Nutzers. Achten Sie darauf, dass die Telefonnummer mit einem vorangestellten + und keinen anderen Satzzeichen oder Leerzeichen (für Beispiel: +15105551234)

    Swift

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

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

    Als Best Practice wird empfohlen, die Nutzer vorab darüber zu informieren, dass sie eine SMS erhalten und dabei die üblichen Gebühren anfallen.

    Die Methode verifyPhoneNumber() startet den App-Bestätigungsprozess im Hintergrund mit lautloser Push-Benachrichtigung. Wenn keine Push-Benachrichtigung verfügbar ist, wird stattdessen eine reCAPTCHA-Herausforderung ausgegeben.

  5. Nachdem der SMS-Code gesendet wurde, bitten Sie den Nutzer, den Code zu bestätigen. Verwenden Sie dann Antwort zum Erstellen eines PhoneAuthCredential:

    Swift

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

    Objective-C

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

    Swift

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

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

    Swift

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

    Objective-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:

Swift

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

Objective-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ückwunsch! Sie haben erfolgreich einen zweiten Authentifizierungsfaktor für einen Nutzer registriert.

Nutzer mit einem zweiten Faktor anmelden

So melden Sie einen Nutzer mit der SMS-Bestätigung in zwei Schritten an:

  1. Melden Sie den Nutzer mit dessen erstem Faktor an. Dann sehen Sie einen Fehler, der angibt, dass die Multi-Faktor-Authentifizierung erforderlich ist. Dieser Fehler enthält einen Resolver, enthält Hinweise zu den registrierten zweiten Faktoren und einer zugrunde liegenden Sitzung, die bestätigt, dass der Nutzer mit dem ersten Faktor authentifiziert wurde.

    Wenn der erste Faktor des Nutzers beispielsweise eine E-Mail und ein Passwort war, tun Sie Folgendes:

    Swift

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

    Objective-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 Nutzers ein föderierter Anbieter wie OAuth ist, rufen Sie nach dem Aufruf von getCredentialWith() den Fehler ab.

  2. Wenn der Nutzer mehrere sekundäre Faktoren registriert hat, fragen Sie ihn, welchen zu verwenden. Sie erhalten die maskierte Telefonnummer mit resolver.hints[selectedIndex].phoneNumber und der Anzeigename mit resolver.hints[selectedIndex].displayName.

    Swift

    // Ask user which second factor to use. Then:
    if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID {
      // User selected a phone second factor.
      // ...
    } else if resolver.hints[selectedIndex].factorID == TotpMultiFactorID {
      // User selected a TOTP second factor.
      // ...
    } else {
      // Unsupported second factor.
    }
    

    Objective-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 if (hint.factorID == FIRTOTPMultiFactorID) {
      // User selected a TOTP second factor.
      // ...
    } else {
      // Unsupported second factor.
    }
    
  3. Senden Sie eine Bestätigungsnachricht an das Mobiltelefon des Nutzers:

    Swift

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

    Objective-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. Bitten Sie nach dem Senden des SMS-Codes den Nutzer, den Code zu bestätigen und für folgende Aktionen zu verwenden: Erstellen Sie ein PhoneAuthCredential:

    Swift

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

    Objective-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 Anmeldedaten:

    Swift

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    Objective-C

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. Schließen Sie die Anmeldung. Sie können dann auf das ursprüngliche Anmeldeergebnis zugreifen, das die anbieterspezifischen Daten und Anmeldedaten zur Authentifizierung enthält:

    Swift

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

    Objective-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-Faktor-Nutzers:

Swift

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

Objective-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ückwunsch! Sie haben sich erfolgreich mit einer Multi-Faktor-Authentifizierung für einen Nutzer angemeldet.

Nächste Schritte