Authentifizieren Sie sich mit Apple und C++

Sie können Ihren Benutzern ermöglichen, sich bei Firebase mit ihrer Apple-ID zu authentifizieren, indem Sie das Firebase SDK verwenden, um den End-to-End-OAuth 2.0-Anmeldeablauf auszuführen.

Bevor Sie beginnen

Um Benutzer mit Apple anzumelden, konfigurieren Sie zunächst „Mit Apple anmelden“ auf der Entwickler-Website von Apple und aktivieren Sie dann Apple als Anmeldeanbieter für Ihr Firebase-Projekt.

Treten Sie dem Apple-Entwicklerprogramm bei

Mit Apple anmelden kann nur von Mitgliedern des Apple Developer Program konfiguriert werden.

Konfigurieren Sie die Anmeldung mit Apple

Die Apple-Anmeldung muss in Ihrem Firebase-Projekt aktiviert und ordnungsgemäß konfiguriert sein. Die Konfiguration variiert je nach Android- und Apple-Plattform. Bitte folgen Sie dem Abschnitt „Konfigurieren der Anmeldung mit Apple“ in den Anleitungen für Apple-Plattformen und/oder Android , bevor Sie fortfahren.

Aktivieren Sie Apple als Anmeldeanbieter

  1. Öffnen Sie in der Firebase-Konsole den Abschnitt Auth . Aktivieren Sie auf der Registerkarte Anmeldemethode den Apple -Anbieter.
  2. Konfigurieren Sie die Einstellungen des Apple-Anmeldeanbieters:
    1. Wenn Sie Ihre App nur auf Apple-Plattformen bereitstellen, können Sie die Felder „Service-ID“, „Apple-Team-ID“, „Privater Schlüssel“ und „Schlüssel-ID“ leer lassen.
    2. Für Support auf Android-Geräten:
      1. Fügen Sie Ihrem Android-Projekt Firebase hinzu . Achten Sie darauf, die SHA-1-Signatur Ihrer App zu registrieren, wenn Sie Ihre App in der Firebase-Konsole einrichten.
      2. Öffnen Sie in der Firebase-Konsole den Abschnitt Auth . Aktivieren Sie auf der Registerkarte Anmeldemethode den Apple -Anbieter. Geben Sie die Service-ID an, die Sie im vorherigen Abschnitt erstellt haben. Geben Sie außerdem im Abschnitt OAuth-Codeflusskonfiguration Ihre Apple-Team-ID sowie den privaten Schlüssel und die Schlüssel-ID an, die Sie im vorherigen Abschnitt erstellt haben.

Erfüllen Sie die Anforderungen von Apple an anonymisierte Daten

Mit Apple anmelden bietet Benutzern die Möglichkeit, ihre Daten, einschließlich ihrer E-Mail-Adresse, bei der Anmeldung zu anonymisieren. Benutzer, die diese Option wählen, haben E-Mail-Adressen mit der Domäne privaterelay.appleid.com . Wenn Sie „Mit Apple anmelden“ in Ihrer App verwenden, müssen Sie alle geltenden Entwicklerrichtlinien oder Bedingungen von Apple in Bezug auf diese anonymisierten Apple-IDs einhalten.

Dazu gehört auch das Einholen der erforderlichen Benutzereinwilligung, bevor Sie direkt identifizierende personenbezogene Daten mit einer anonymisierten Apple-ID verknüpfen. Bei Verwendung der Firebase-Authentifizierung kann dies die folgenden Aktionen umfassen:

  • Verknüpfen Sie eine E-Mail-Adresse mit einer anonymisierten Apple-ID oder umgekehrt.
  • Verknüpfen Sie eine Telefonnummer mit einer anonymisierten Apple-ID oder umgekehrt
  • Verknüpfen Sie einen nicht anonymen Social Credential (Facebook, Google usw.) mit einer anonymisierten Apple ID oder umgekehrt.

Die obige Liste ist nicht vollständig. Lesen Sie die Lizenzvereinbarung für das Apple-Entwicklerprogramm im Abschnitt „Mitgliedschaft“ Ihres Entwicklerkontos, um sicherzustellen, dass Ihre App die Anforderungen von Apple erfüllt.

Greifen Sie auf die Klasse firebase::auth::Auth zu

Die Auth -Klasse ist das Gateway für alle API-Aufrufe.
  1. Fügen Sie die Auth- und App-Header-Dateien hinzu:
    #include "firebase/app.h"
    #include "firebase/auth.h"
    
  2. Erstellen Sie in Ihrem Initialisierungscode eine firebase::App -Klasse.
    #if defined(__ANDROID__)
      firebase::App* app =
          firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity);
    #else
      firebase::App* app = firebase::App::Create(firebase::AppOptions());
    #endif  // defined(__ANDROID__)
    
  3. Erwerben Sie die Klasse firebase::auth::Auth für Ihre firebase::App . Es gibt eine Eins-zu-Eins-Zuordnung zwischen App und Auth .
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

Behandeln Sie den Anmeldevorgang mit dem Firebase SDK

Der Vorgang zum Anmelden mit Apple variiert je nach Apple- und Android-Plattform.

Auf Apple-Plattformen

Authentifizieren Sie Ihre Benutzer mit Firebase über das Apple Sign In Objective-C SDK, das von Ihrem C++-Code aufgerufen wird.

  1. Generieren Sie für jede Anmeldeanforderung eine zufällige Zeichenfolge – eine „Nonce“ –, die Sie verwenden, um sicherzustellen, dass das ID-Token, das Sie erhalten, speziell als Antwort auf die Authentifizierungsanforderung Ihrer App gewährt wurde. Dieser Schritt ist wichtig, um Replay-Angriffe zu verhindern.

      - (NSString *)randomNonce:(NSInteger)length {
        NSAssert(length > 0, @"Expected nonce to have positive length");
        NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._";
        NSMutableString *result = [NSMutableString string];
        NSInteger remainingLength = length;
    
        while (remainingLength > 0) {
          NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16];
          for (NSInteger i = 0; i < 16; i++) {
            uint8_t random = 0;
            int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random);
            NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode);
    
            [randoms addObject:@(random)];
          }
    
          for (NSNumber *random in randoms) {
            if (remainingLength == 0) {
              break;
            }
    
            if (random.unsignedIntValue < characterSet.length) {
              unichar character = [characterSet characterAtIndex:random.unsignedIntValue];
              [result appendFormat:@"%C", character];
              remainingLength--;
            }
          }
        }
      }
    
    

    Sie senden den SHA256-Hash der Nonce mit Ihrer Anmeldeanforderung, die Apple unverändert in der Antwort weitergibt. Firebase validiert die Antwort, indem es die ursprüngliche Nonce hasht und mit dem von Apple übergebenen Wert vergleicht.

  2. Starten Sie den Anmeldeablauf von Apple, einschließlich des SHA256-Hashes der Nonce und der Delegate-Klasse, die Apples Antwort verarbeiten wird (siehe nächster Schritt):

      - (void)startSignInWithAppleFlow {
        NSString *nonce = [self randomNonce:32];
        self.currentNonce = nonce;
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest];
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        request.nonce = [self stringBySha256HashingString:nonce];
    
        ASAuthorizationController *authorizationController =
            [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
        authorizationController.delegate = self;
        authorizationController.presentationContextProvider = self;
        [authorizationController performRequests];
      }
    
      - (NSString *)stringBySha256HashingString:(NSString *)input {
        const char *string = [input UTF8String];
        unsigned char result[CC_SHA256_DIGEST_LENGTH];
        CC_SHA256(string, (CC_LONG)strlen(string), result);
    
        NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
        for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
          [hashed appendFormat:@"%02x", result[i]];
        }
        return hashed;
      }
    
  3. Behandeln Sie die Antwort von Apple in Ihrer Implementierung von ASAuthorizationControllerDelegate`. Wenn die Anmeldung erfolgreich war, verwenden Sie das ID-Token aus der Antwort von Apple mit dem ungehashten Nonce, um sich bei Firebase zu authentifizieren:

      - (void)authorizationController:(ASAuthorizationController *)controller
         didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
        if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
          ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
          NSString *rawNonce = self.currentNonce;
          NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent.");
    
          if (appleIDCredential.identityToken == nil) {
            NSLog(@"Unable to fetch identity token.");
            return;
          }
    
          NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken
                                                    encoding:NSUTF8StringEncoding];
          if (idToken == nil) {
            NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken);
          }
        }
    
  4. Verwenden Sie die resultierende Token-Zeichenfolge und die ursprüngliche Nonce, um eine Firebase-Anmeldeinformation zu erstellen und sich bei Firebase anzumelden.

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  5. Dasselbe Muster kann mit Reauthenticate verwendet werden, das verwendet werden kann, um neue Anmeldeinformationen für vertrauliche Vorgänge abzurufen, die eine kürzlich erfolgte Anmeldung erfordern.

    firebase::Future<firebase::auth::SignInResult> result =
        user->Reauthenticate(credential);
    
  6. Das gleiche Muster kann verwendet werden, um ein Konto mit Apple Sign In zu verknüpfen. Es kann jedoch ein Fehler auftreten, wenn ein vorhandenes Firebase-Konto bereits mit dem Apple-Konto verknüpft wurde, mit dem Sie eine Verknüpfung herstellen möchten. Wenn dies auftritt, gibt das future einen Status von kAuthErrorCredentialAlreadyInUse und das UserInfo-Objekt von SignInResult kann ein gültiges updated_credential enthalten. Diese Anmeldeinformationen können verwendet werden, um sich über SignInWithCredential bei dem mit Apple verknüpften Konto anzumelden, ohne dass ein weiteres Apple-Anmeldetoken und eine Nonce generiert werden müssen.

    Beachten Sie, dass Sie LinkAndRetrieveDataWithCredential verwenden müssen, damit dieser Vorgang die Anmeldeinformationen enthält, da updated_credential ein Mitglied des SignInResult.UserInfo Objekts ist.

    firebase::Future<firebase::auth::SignInResult> link_result =
        auth->current_user()->LinkAndRetrieveDataWithCredential(credential);
    
    // To keep example simple, wait on the current thread until call completes.
    while (link_result.status() == firebase::kFutureStatusPending) {
      Wait(100);
    }
    
    // Determine the result of the link attempt
    if (link_result.error() == firebase::auth::kAuthErrorNone) {
      // user linked correctly.
    } else if (link_result.error() ==
                   firebase::auth::kAuthErrorCredentialAlreadyInUse &&
               link_result.result()->info.updated_credential.is_valid()) {
      // Sign In with the new credential
      firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential(
          link_result.result()->info.updated_credential);
    } else {
      // Another link error occurred.
    }
    

Auf Android

Authentifizieren Sie Ihre Benutzer unter Android mit Firebase, indem Sie die webbasierte generische OAuth-Anmeldung mithilfe des Firebase SDK in Ihre App integrieren, um den End-to-End-Anmeldevorgang durchzuführen.

Führen Sie die folgenden Schritte aus, um den Anmeldevorgang mit dem Firebase SDK zu verarbeiten:

  1. Erstellen Sie eine Instanz von FederatedOAuthProviderData , die mit der für Apple geeigneten Anbieter-ID konfiguriert ist.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. Optional: Geben Sie zusätzliche OAuth 2.0-Bereiche über den Standard hinaus an, die Sie vom Authentifizierungsanbieter anfordern möchten.

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. Optional: Wenn Sie den Anmeldebildschirm von Apple in einer anderen Sprache als Englisch anzeigen möchten, legen Sie den locale -Parameter fest. Informationen zu den unterstützten Gebietsschemas finden Sie in den Dokumenten zum Anmelden mit Apple .

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. Sobald Ihre Anbieterdaten konfiguriert sind, verwenden Sie sie, um einen FederatedOAuthProvider zu erstellen.

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Authentifizieren Sie sich bei Firebase mithilfe des Auth-Anbieterobjekts. Beachten Sie, dass dies im Gegensatz zu anderen FirebaseAuth-Vorgängen die Kontrolle über Ihre Benutzeroberfläche übernimmt, indem eine Webansicht angezeigt wird, in der der Benutzer seine Anmeldeinformationen eingeben kann.

    Um den Anmeldeablauf zu starten, rufen signInWithProvider :

    firebase::Future<firebase::auth::SignInResult> result =
      auth->SignInWithProvider(provider_data);
    

    Ihre Anwendung kann dann warten oder einen Rückruf auf dem Future registrieren .

  6. Dasselbe Muster kann mit ReauthenticateWithProvider verwendet werden, das verwendet werden kann, um neue Anmeldeinformationen für vertrauliche Vorgänge abzurufen, die eine kürzlich erfolgte Anmeldung erfordern.

    firebase::Future<firebase::auth::SignInResult> result =
      user->ReauthenticateWithProvider(provider_data);
    

    Ihre Anwendung kann dann warten oder einen Rückruf auf dem Future registrieren .

  7. Und Sie können linkWithCredential() verwenden, um verschiedene Identitätsanbieter mit bestehenden Konten zu verknüpfen.

    Beachten Sie, dass Apple verlangt, dass Sie die ausdrückliche Zustimmung der Benutzer einholen, bevor Sie ihre Apple-Konten mit anderen Daten verknüpfen.

    Um beispielsweise ein Facebook-Konto mit dem aktuellen Firebase-Konto zu verknüpfen, verwenden Sie das Zugriffstoken, das Sie erhalten haben, als Sie den Benutzer bei Facebook angemeldet haben:

    // Initialize a Facebook credential with a Facebook access token.
    AuthCredential credential =
        firebase::auth::FacebookAuthProvider.getCredential(token);
    
    // Assuming the current user is an Apple user linking a Facebook provider.
    firebase::Future<firebase::auth::SignInResult> result =
        auth.getCurrentUser().linkWithCredential(credential);
    

Melden Sie sich mit Apple Notes an

Im Gegensatz zu anderen Anbietern, die von Firebase Auth unterstützt werden, stellt Apple keine Foto-URL bereit.

Wenn der Benutzer sich entscheidet, seine E-Mail-Adresse nicht mit der App zu teilen, stellt Apple eine eindeutige E-Mail-Adresse für diesen Benutzer (in der Form xyz@privaterelay.appleid.com ) bereit, die es mit Ihrer App teilt. Wenn Sie den privaten E-Mail-Weiterleitungsdienst konfiguriert haben, leitet Apple an die anonymisierte Adresse gesendete E-Mails an die echte E-Mail-Adresse des Benutzers weiter.

Apple teilt Benutzerinformationen wie den Anzeigenamen nur mit Apps, wenn sich ein Benutzer zum ersten Mal anmeldet. Normalerweise speichert Firebase den Anzeigenamen, wenn sich ein Benutzer zum ersten Mal bei Apple anmeldet, den Sie mit getCurrentUser().getDisplayName() können. Wenn Sie jedoch zuvor Apple verwendet haben, um einen Benutzer bei der App anzumelden, ohne Firebase zu verwenden, stellt Apple Firebase nicht den Anzeigenamen des Benutzers bereit.

Nächste Schritte

Nachdem sich ein Benutzer zum ersten Mal angemeldet hat, wird ein neues Benutzerkonto erstellt und mit den Anmeldeinformationen verknüpft – d. h. dem Benutzernamen und Kennwort, der Telefonnummer oder den Authentifizierungsanbieterinformationen –, mit denen sich der Benutzer angemeldet hat. Dieses neue Konto wird als Teil Ihres Firebase-Projekts gespeichert und kann verwendet werden, um einen Benutzer in jeder App in Ihrem Projekt zu identifizieren, unabhängig davon, wie sich der Benutzer anmeldet.

In Ihren Apps können Sie die grundlegenden Profilinformationen des Benutzers aus dem Objekt firebase::auth::user abrufen. Siehe Benutzer verwalten .

In Ihren Firebase-Echtzeitdatenbank- und Cloudspeicher-Sicherheitsregeln können Sie die eindeutige Benutzer-ID des angemeldeten Benutzers aus der auth-Variable abrufen und damit steuern, auf welche Daten ein Benutzer zugreifen kann.