Uwierzytelnij przez Apple i C++

Możesz umożliwić użytkownikom uwierzytelnianie się w Firebase za pomocą identyfikatora Apple, korzystając z pakietu Firebase SDK do przeprowadzenia pełnego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby umożliwić użytkownikom logowanie się za pomocą Apple, najpierw skonfiguruj logowanie przez Apple w witrynie dla deweloperów Apple, a potem włącz Apple jako dostawcę logowania w projekcie w Firebase.

Dołącz do programu Apple Developer Program

Logowanie przez Apple mogą skonfigurować tylko członkowie programu Apple Developer Program.

Skonfiguruj logowanie przez Apple

Logowanie przez Apple musi być włączone i prawidłowo skonfigurowane w projekcie w Firebase. Konfiguracja różni się w zależności od platformy Android i Apple. Zanim przejdziesz dalej, zapoznaj się z sekcją "Konfigurowanie logowania przez Apple" w przewodnikach dotyczących platform Apple lub Androida.

Włącz Apple jako dostawcę logowania

  1. W konsoli Firebase otwórz Zabezpieczenia > Uwierzytelnianie.
  2. Na karcie Metoda logowania włącz dostawcę logowania Apple.
  3. Skonfiguruj ustawienia dostawcy logowania przez Apple:
    • Apple: jeśli wdrażasz aplikację tylko na platformach Apple możesz pozostawić puste pola Identyfikator usługi, Identyfikator zespołu Apple, Klucz prywatny i Identyfikator klucza.
    • Android: aby obsługiwać urządzenia z Androidem, wykonaj te czynności:
      1. Dodaj Firebase do projektu aplikacji na Androida.
      2. Jeśli jeszcze tego nie zrobisz, określ odcisk cyfrowy SHA-1 aplikacji.
        1. W konsoli Firebase otwórz kartę Ustawienia > Ogólne tab.
        2. Przewiń w dół do karty Twoje aplikacje , wybierz aplikację na Androida i dodaj odcisk cyfrowy SHA-1 w polu Odciski cyfrowe certyfikatu SHA.

        Więcej informacji o tym, jak uzyskać odcisk cyfrowy SHA aplikacji, znajdziesz w artykule Uwierzytelnianie klienta.

      3. Skonfiguruj ustawienia dostawcy logowania przez Apple:
        1. W konsoli Firebase otwórz Zabezpieczenia > Uwierzytelnianie.
        2. Na karcie Metoda logowania kliknij dostawcę logowania Apple.
        3. Określ identyfikator usługi utworzony w poprzedniej sekcji. W sekcji konfiguracji przepływu kodu OAuth określ też identyfikator zespołu Apple oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Spełnij wymagania Apple dotyczące anonimizacji danych

Logowanie przez Apple daje użytkownikom możliwość anonimizacji danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, będą mieli adresy e-mail z domeną privaterelay.appleid.com. Jeśli używasz logowania przez Apple w swojej aplikacji, musisz przestrzegać wszystkich obowiązujących zasad i warunków dla deweloperów Apple dotyczących tych anonimowych identyfikatorów Apple.

Obejmuje to uzyskanie wymaganej zgody użytkownika przed powiązaniem bezpośrednio identyfikujących danych osobowych z anonimowym identyfikatorem Apple. W przypadku korzystania z uwierzytelniania Firebase może to obejmować te działania:

  • powiązanie adresu e-mail z anonimowym identyfikatorem Apple lub odwrotnie;
  • powiązanie numeru telefonu z anonimowym identyfikatorem Apple lub odwrotnie;
  • powiązanie nieanonimowych danych logowania w mediach społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Aby mieć pewność, że Twoja aplikacja spełnia wymagania Apple, zapoznaj się z umową licencyjną programu Apple Developer Program w sekcji Członkostwo na koncie dewelopera.

Dostęp do zajęć firebase::auth::Auth

Klasa Auth jest bramą do wszystkich wywołań interfejsu API.
  1. Dodaj pliki nagłówkowe Auth i App:
    #include "firebase/app.h"
    #include "firebase/auth.h"
  2. W kodzie inicjującym utwórz a firebase::App klasę.
    #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. Pobierz zajęcia firebase::auth::Auth dla firebase::App. Istnieje mapowanie 1:1 między App a Auth.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);

Obsługa procesu logowania za pomocą pakietu Firebase SDK

Proces logowania przez Apple różni się w zależności od platformy Apple i Androida.

Na platformach Apple

Uwierzytelniaj użytkowników w Firebase za pomocą pakietu Apple Sign In Objective-C SDK wywoływanego z kodu C++.

  1. W przypadku każdego żądania logowania wygeneruj losowy ciąg znaków – „nonce” – który będzie używany do sprawdzania, czy otrzymany token identyfikatora został przyznany specjalnie w odpowiedzi na żądanie uwierzytelnienia aplikacji. Ten krok jest ważny, aby zapobiec atakom typu replay.

      - (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--;
            }
          }
        }
      }
    
    

    W żądaniu logowania wyślesz skrót SHA256 nonce, który Apple przekaże w odpowiedzi bez zmian. Firebase weryfikuje odpowiedź, obliczając skrót oryginalnego nonce i porównując go z wartością przekazaną przez Apple.

  2. Uruchom proces logowania przez Apple, w tym w żądaniu skrót SHA256 liczby jednorazowej i klasę delegata, która będzie obsługiwać odpowiedź Apple (patrz następny krok):

      - (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. Obsłuż odpowiedź Apple w implementacji `ASAuthorizationControllerDelegate`. Jeśli logowanie się zakończyło się powodzeniem, użyj tokena identyfikatora z odpowiedzi Apple z niezaszyfrowanym nonce do uwierzytelnienia w Firebase:

      - (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. Użyj wynikowego ciągu tokena i oryginalnej liczby jednorazowej, aby utworzyć dane logowania Firebase i zalogować się w Firebase.

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  5. Tego samego wzorca można używać z Reauthenticate, aby pobierać nowe dane logowania do operacji wrażliwych, które wymagają niedawnego logowania.

    firebase::Future<firebase::auth::AuthResult> result =
        user->Reauthenticate(credential);
    
  6. Tego samego wzorca można używać do łączenia konta z logowaniem przez Apple. Może jednak wystąpić błąd, gdy istniejące konto Firebase jest już połączone z kontem Apple, z którym próbujesz się połączyć. W takim przypadku przyszłość zwróci stan kAuthErrorCredentialAlreadyInUse, a AuthResult może zawierać prawidłowe credential. Tych danych logowania można użyć do zalogowania się na połączone z Apple konto za pomocą SignInAndRetrieveDataWithCredential bez konieczności generowania kolejnego tokena i liczby jednorazowej logowania przez Apple.

    firebase::Future<firebase::auth::AuthResult> link_result =
        auth->current_user().LinkWithCredential(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()
                   ->additional_user_info.updated_credential.is_valid()) {
      // Sign In with the new credential
      firebase::Future<firebase::auth::AuthResult> result =
          auth->SignInAndRetrieveDataWithCredential(
              link_result.result()->additional_user_info.updated_credential);
    } else {
      // Another link error occurred.
    }

W Androidzie

W Androidzie uwierzytelniaj użytkowników w Firebase, integrując ogólne logowanie OAuth w internecie z aplikacją za pomocą pakietu Firebase SDK, aby przeprowadzić pełny proces logowania.

Aby obsługiwać proces logowania za pomocą pakietu Firebase SDK, wykonaj te czynności:

  1. Utwórz instancję FederatedOAuthProviderData skonfigurowaną z identyfikatorem dostawcy odpowiednim dla Apple.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. Opcjonalnie: określ dodatkowe zakresy protokołu OAuth 2.0 poza domyślnymi, o które chcesz poprosić dostawcę uwierzytelniania.

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. Opcjonalnie: jeśli chcesz wyświetlać ekran logowania Apple w innym języku niż angielski, ustaw parametr locale. Obsługiwane ustawienia regionalne znajdziesz w dokumentacji logowania przez Apple.

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. Gdy dane dostawcy zostaną skonfigurowane, użyj ich do utworzenia FederatedOAuthProvider.

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Uwierzytelnij się w Firebase za pomocą obiektu dostawcy Uwierzytelniania. Pamiętaj, że w przeciwieństwie do innych operacji FirebaseAuth ta operacja przejmie kontrolę nad interfejsem użytkownika, wyświetlając widok internetowy, w którym użytkownik może wpisać swoje dane logowania.

    Aby rozpocząć proces logowania, wywołaj signInWithProvider:

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

    Aplikacja może wtedy poczekać lub zarejestrować wywołanie zwrotne w przyszłości.

  6. Tego samego wzorca można używać z ReauthenticateWithProvider, aby pobierać nowe dane logowania do operacji wrażliwych, które wymagają niedawnego logowania.

    firebase::Future<firebase::auth::AuthResult> result =
      user.ReauthenticateWithProvider(provider_data);
    

    Aplikacja może wtedy poczekać lub zarejestrować wywołanie zwrotne w przyszłości.

  7. Możesz też użyć LinkWithCredential(), aby połączyć różnych dostawców tożsamości z istniejącymi kontami.

    Pamiętaj, że Apple wymaga uzyskania wyraźnej zgody użytkowników przed połączeniem ich kont Apple z innymi danymi.

    Aby na przykład połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu uzyskanego podczas logowania użytkownika na Facebooku:

    // 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::AuthResult> result =
        auth.current_user().LinkWithCredential(credential);
    

Uwagi dotyczące logowania przez Apple

W przeciwieństwie do innych dostawców obsługiwanych przez Uwierzytelnianie Firebase Apple nie udostępnia adresu URL zdjęcia.

Gdy użytkownik zdecyduje się nie udostępniać swojego adresu e-mail aplikacji, Apple udostępnia mu unikalny adres e-mail (w formacie xyz@privaterelay.appleid.com), który udostępnia Twojej aplikacji. Jeśli skonfigurujesz usługę prywatnego przekazywania e-maili, Apple będzie przekazywać e-maile wysyłane na anonimowy adres na prawdziwy adres e-mail użytkownika.

Apple udostępnia aplikacjom informacje o użytkowniku, takie jak nazwa wyświetlana, tylko przy pierwszym logowaniu. Zwykle Firebase zapisuje nazwę wyświetlaną przy pierwszym logowaniu użytkownika przez Apple, którą możesz uzyskać za pomocą current_user().display_name(). Jeśli jednak wcześniej logowałeś(-aś) użytkownika w aplikacji za pomocą Apple bez użycia Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Dalsze kroki

Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone z danymi logowania – nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania – za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane jako część projektu w Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w projekcie, niezależnie od sposobu logowania.

W aplikacjach możesz uzyskać podstawowe informacje o profilu użytkownika z obiektu firebase::auth::User. Zobacz Zarządzanie użytkownikami.

W regułach bezpieczeństwa bazy danych czasu rzeczywistego Firebase i Cloud Storage możesz uzyskać unikalny identyfikator użytkownika zalogowanego z zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik może mieć dostęp.