Uwierzytelnij się za pomocą Apple i C++

Możesz zezwolić użytkownikom na uwierzytelnianie w Firebase przy użyciu ich identyfikatora Apple ID przy użyciu pakietu Firebase SDK do przeprowadzania kompleksowego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby logować użytkowników za pomocą Apple, najpierw skonfiguruj opcję Logowanie się z Apple w witrynie dla programistów Apple, a następnie włącz Apple jako dostawcę logowania dla swojego projektu Firebase.

Dołącz do Programu dla programistów Apple

Logowanie się przez Apple może być skonfigurowane tylko przez członków programu Apple Developer Program .

Skonfiguruj logowanie za pomocą Apple

Logowanie Apple musi być włączone i odpowiednio skonfigurowane w projekcie Firebase. Konfiguracja różni się w zależności od platformy Android i Apple. Przed kontynuowaniem postępuj zgodnie z sekcją „Konfiguruj logowanie za pomocą Apple” w przewodnikach dotyczących platform Apple i/lub systemu Android .

Włącz Apple jako dostawcę logowania

  1. W konsoli Firebase otwórz sekcję Auth . Na karcie Metoda logowania włącz dostawcę Apple .
  2. Skonfiguruj ustawienia dostawcy logowania Apple:
    1. Jeśli wdrażasz swoją aplikację tylko na platformach Apple, możesz pozostawić pola Service ID, Apple Team ID, private key i key ID puste.
    2. Aby uzyskać pomoc dotyczącą urządzeń z systemem Android:
      1. Dodaj Firebase do swojego projektu na Androida . Pamiętaj, aby zarejestrować podpis SHA-1 aplikacji podczas konfigurowania aplikacji w konsoli Firebase.
      2. W konsoli Firebase otwórz sekcję Auth . Na karcie Metoda logowania włącz dostawcę Apple . Określ identyfikator usługi utworzony w poprzedniej sekcji. Ponadto w sekcji konfiguracji przepływu kodu OAuth podaj swój Apple Team ID oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Przestrzegaj wymagań Apple dotyczących danych anonimowych

Funkcja Zaloguj się z Apple umożliwia użytkownikom anonimizację danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, mają adresy e-mail w domenie privaterelay.appleid.com . Gdy używasz Logowania się przez Apple w swojej aplikacji, musisz przestrzegać wszelkich obowiązujących zasad deweloperskich lub warunków Apple dotyczących tych anonimowych identyfikatorów Apple ID.

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

  • Połącz adres e-mail z anonimowym identyfikatorem Apple ID lub odwrotnie.
  • Połącz numer telefonu z anonimowym identyfikatorem Apple ID lub odwrotnie
  • Połącz nieanonimowe dane uwierzytelniające z serwisów społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple ID lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Zapoznaj się z Umową licencyjną Apple Developer Program w sekcji Członkostwo na swoim koncie programisty, aby upewnić się, że Twoja aplikacja spełnia wymagania Apple.

Uzyskaj dostęp do klasy firebase::auth::Auth

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

Obsługuj proces logowania za pomocą Firebase SDK

Proces logowania się 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ą zestawu Apple Sign In Objective-C SDK wywoływanego z kodu C++.

  1. Dla każdego żądania logowania wygeneruj losowy ciąg — „nonce” — którego użyjesz, aby upewnić się, że otrzymany token identyfikatora został przyznany specjalnie w odpowiedzi na żądanie uwierzytelnienia Twojej aplikacji. Ten krok jest ważny, aby zapobiec atakom powtórkowym.

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

    Wraz z żądaniem logowania wyślesz skrót SHA256 identyfikatora jednorazowego, który Apple przekaże niezmieniony w odpowiedzi. Firebase weryfikuje odpowiedź, mieszając oryginalny identyfikator jednorazowy i porównując go z wartością przekazaną przez Apple.

  2. Rozpocznij proces logowania Apple, uwzględniając w swoim żądaniu skrót SHA256 wartości jednorazowej i klasę delegata, która będzie obsługiwać odpowiedź firmy Apple (zobacz 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ługuj odpowiedź Apple w swojej implementacji ASAuthorizationControllerDelegate`. Jeśli logowanie się powiodło, użyj tokena identyfikatora z odpowiedzi Apple z niehaszowaną wartością jednorazową, aby uwierzytelnić się 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 wartości jednorazowej, aby utworzyć poświadczenie Firebase i zalogować się do 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żyć z Reauthenticate , która może służyć do pobierania świeżych poświadczeń dla poufnych operacji wymagających niedawnego logowania.

    firebase::Future<firebase::auth::AuthResult> result =
        user->Reauthenticate(credential);
    
  6. Ten sam wzór można wykorzystać do połączenia konta z Apple Sign In. Możesz jednak napotkać błąd, gdy istniejące konto Firebase zostało już połączone z kontem Apple, z którym próbujesz się połączyć. Kiedy to nastąpi, przyszłość zwróci stan kAuthErrorCredentialAlreadyInUse , a AuthResult może zawierać prawidłowe credential . Tego poświadczenia można użyć do zalogowania się na konto połączone z firmą Apple za pośrednictwem SignInAndRetrieveDataWithCredential bez konieczności generowania kolejnego tokena logowania Apple i jednorazowego użytku.

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

Na Androida

W systemie Android uwierzytelniaj użytkowników za pomocą Firebase, integrując w swojej aplikacji ogólne internetowe logowanie OAuth za pomocą pakietu Firebase SDK, aby przeprowadzić pełny proces logowania.

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

  1. Skonstruuj instancję FederatedOAuthProviderData skonfigurowaną z identyfikatorem dostawcy odpowiednim dla firmy Apple.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. Opcjonalnie: Określ dodatkowe zakresy OAuth 2.0 wykraczające poza zakres domyślny, 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świetlić ekran logowania Apple w języku innym niż angielski, ustaw parametr ustawień locale . Zapoznaj się z dokumentacją Logowanie się za pomocą Apple, aby poznać obsługiwane języki.

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. Po skonfigurowaniu danych dostawcy 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 przy użyciu obiektu dostawcy uwierzytelniania. Pamiętaj, że w przeciwieństwie do innych operacji FirebaseAuth, przejmie to kontrolę nad interfejsem użytkownika, wyświetlając widok internetowy, w którym użytkownik może wprowadzić swoje dane uwierzytelniające.

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

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

    Twoja aplikacja może wtedy czekać lub zarejestrować wywołanie zwrotne w Future .

  6. Tego samego wzorca można użyć z ReauthenticateWithProvider , który może służyć do pobierania świeżych poświadczeń dla poufnych operacji wymagających niedawnego logowania.

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

    Twoja aplikacja może wtedy czekać lub zarejestrować wywołanie zwrotne w Future .

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

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

    Na przykład, aby połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu otrzymanego po zalogowaniu 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);
    

Zaloguj się za pomocą Notatek Apple

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

Ponadto, gdy użytkownik zdecyduje się nie udostępniać aplikacji swojego adresu e-mail, firma Apple przydziela mu unikalny adres e-mail (w postaci xyz@privaterelay.appleid.com ), który udostępnia aplikacji. Jeśli skonfigurowałeś usługę przekazywania prywatnych wiadomości e-mail, Apple przekazuje wiadomości e-mail wysł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 użytkownika. Zwykle Firebase przechowuje nazwę wyświetlaną przy pierwszym logowaniu użytkownika w Apple, którą można uzyskać za pomocą current_user().display_name() . Jeśli jednak wcześniej używałeś Apple do logowania użytkownika w aplikacji bez korzystania z Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania — za pomocą których użytkownik się logował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikacji użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, jak użytkownik się loguje.

W swoich 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 Firebase Realtime Database i Cloud Storage możesz uzyskać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.