Uwierzytelnij przez Apple i C++

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

Zanim zaczniesz

Aby logować użytkowników przy użyciu urządzenia Apple, najpierw skonfiguruj funkcję Zaloguj się przez Apple w witrynie dla deweloperów Apple, a potem włącz Apple jako dostawcę logowania w swoim projekcie Firebase.

Dołącz do programu dla deweloperów Apple

Funkcja Zaloguj się przez Apple może skonfigurować tylko członkowie programu dla deweloperów Apple.

Skonfiguruj logowanie się przez Apple

Musisz włączyć i prawidłowo skonfigurować logowanie przez Apple w swoim projekcie Firebase. Konfiguracja różni się w zależności od platformy Android i platformy Apple. Zanim przejdziesz dalej, wykonaj czynności opisane w sekcji „Skonfiguruj logowanie się przez Apple” w przewodnikach na platformach Apple lub Androidzie.

Włącz Apple jako dostawcę logowania

  1. W konsoli Firebase otwórz sekcję Uwierzytelnianie. Na karcie Metoda logowania włącz dostawcę Apple.
  2. Skonfiguruj ustawienia dostawcy logowania przez Apple:
    1. Jeśli wdrażasz aplikację tylko na platformach Apple, pola identyfikatora usługi, identyfikatora zespołu Apple, klucza prywatnego i identyfikatora klucza możesz pozostawić puste.
    2. Aby uzyskać pomoc dotyczącą urządzeń z Androidem:
      1. Dodaj Firebase do swojego projektu na Androida. Pamiętaj, aby podczas konfigurowania aplikacji w konsoli Firebase zarejestrować jej podpis SHA-1.
      2. W konsoli Firebase otwórz sekcję Uwierzytelnianie. Na karcie Metoda logowania włącz dostawcę Apple. Podaj identyfikator usługi utworzony w poprzedniej sekcji. Poza tym w sekcji konfiguracji przepływu kodu OAuth podaj identyfikator zespołu Apple oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Zgodność z wymaganiami firmy Apple dotyczącymi zanonimizowanych danych

Zaloguj się przez Apple umożliwia 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 w swojej aplikacji korzystasz z funkcji Zaloguj się przez Apple, musisz przestrzegać wszystkich obowiązujących zasad dla deweloperów i warunków firmy Apple dotyczących tych zanonimizowanych identyfikatorów Apple.

Obejmuje to uzyskanie wymaganej zgody użytkownika przed powiązaniem danych osobowych umożliwiających bezpośrednią identyfikację z anonimowym identyfikatorem Apple ID. Gdy używasz uwierzytelniania Firebase, może to wiązać się z tymi działaniami:

  • Połącz adres e-mail z anonimowym identyfikatorem Apple ID lub odwrotnie.
  • Łączenie numeru telefonu z anonimowym identyfikatorem Apple ID i odwrotnie
  • Połącz nieanonimowe dane społecznościowe (Facebook, Google itp.) z anonimowym identyfikatorem Apple lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Zapoznaj się z umową licencyjną programu Apple dla deweloperów w sekcji Subskrypcja na koncie dewelopera, aby upewnić się, że Twoja aplikacja spełnia wymagania Apple.

Uzyskaj dostęp do zajęć firebase::auth::Auth

Klasa Auth jest bramą dla wszystkich wywołań interfejsu API.
  1. Dodaj pliki nagłówka uwierzytelniania i aplikacji:
    #include "firebase/app.h"
    #include "firebase/auth.h"
    
  2. W kodzie inicjowania 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. Uzyskaj zajęcia firebase::auth::Auth związane z urządzeniem firebase::App. Między App a Auth występuje mapowanie 1:1.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

Zarejestruj się za pomocą pakietu SDK Firebase

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ą pakietu SDK do logowania Apple Objective-C wywołanego z Twojego kodu w C++.

  1. Dla każdego żądania logowania wygeneruj losowy ciąg znaków (jednorazowy), którego będziesz używać do sprawdzania, czy otrzymany token tożsamości został przyznany 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 wysyłasz identyfikator SHA256 identyfikatora jednorazowego, który Apple przekaże w odpowiedzi bez zmian. Firebase weryfikuje odpowiedź, szyfrując pierwotną liczbę jednorazową i porównując ją z wartością przekazaną przez Apple.

  2. Uruchom proces logowania Apple, m.in. w żądaniu identyfikatora SHA256 wartości jednorazowej oraz klasy delegowanej, 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ługuj odpowiedź Apple w swojej implementacji ASAuthorizationControllerDelegate”. Jeśli logowanie się udało, użyj tokena identyfikatora z odpowiedzi Apple z niezaszyfrowaną liczbą jednorazową, by 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 powstałego ciągu tokena i oryginalnej wartości jednorazowej, aby utworzyć dane uwierzytelniające Firebase i zalogować się w tej usłudze.

    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 zasadą Reauthenticate, która umożliwia pobieranie nowych danych logowania na potrzeby poufnych operacji, które wymagają niedawnego zalogowania.

    firebase::Future<firebase::auth::AuthResult> result =
        user->Reauthenticate(credential);
    
  6. Tego samego wzoru można użyć do połączenia konta z Apple Sign In. Jeśli jednak dotychczasowe konto Firebase zostało już połączone z kontem Apple, z którym próbujesz je połączyć, może wystąpić błąd. W takim przypadku przyszłość zwraca stan kAuthErrorCredentialAlreadyInUse, a AuthResult może zawierać prawidłowy credential. Te dane logowania można używać do logowania się na konto połączone z Apple za pomocą SignInAndRetrieveDataWithCredential bez konieczności generowania kolejnego tokena logowania Apple Sign In.

    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 urządzeniu z Androidem

W przypadku Androida możesz uwierzytelniać użytkowników w Firebase, integrując internetowy interfejs logowania OAuth z wykorzystaniem pakietu SDK Firebase w celu przeprowadzenia kompleksowego procesu logowania.

Aby zalogować się za pomocą pakietu SDK Firebase, wykonaj te czynności:

  1. Utwórz instancję FederatedOAuthProviderData skonfigurowaną za pomocą identyfikatora dostawcy odpowiedniego dla Apple.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. Opcjonalnie: określ dodatkowe zakresy protokołu OAuth 2.0 wykraczające poza domyślne, o które chcesz prosić 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 języku innym niż angielski, ustaw parametr locale. Informacje o obsługiwanych regionach znajdziesz w dokumentacji logowania się przez Apple.

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

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Uwierzytelniaj w Firebase za pomocą obiektu dostawcy uwierzytelniania. Pamiętaj, że w przeciwieństwie do innych operacji FirebaseAuth da to kontrolę nad interfejsem użytkownika – wyświetli się widok witryny, w którym użytkownik może wpisać swoje dane logowania.

    Aby rozpocząć procedurę logowania, zadzwoń pod numer signInWithProvider:

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

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

  6. Tego samego wzorca można używać z zasadą ReauthenticateWithProvider, która umożliwia pobieranie nowych danych logowania na potrzeby poufnych operacji, które wymagają niedawnego zalogowania.

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

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

  7. Za pomocą LinkWithCredential() możesz też łą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.

    Aby np. połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu uzyskanego 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ę przez Apple Notes

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

Oprócz tego, gdy użytkownik zdecyduje się nie udostępniać swojego adresu e-mail aplikacji, Apple udostępnia mu unikalny adres e-mail (w formie formularza xyz@privaterelay.appleid.com), który udostępnia aplikacji. Jeśli masz skonfigurowaną prywatną usługę przekaźnika, Apple przekazuje e-maile wysyłane na anonimowy adres na rzeczywisty adres użytkownika.

Apple udostępnia aplikacjom informacje o użytkowniku, takie jak wyświetlana nazwa, tylko przy pierwszym logowaniu użytkownika. Zwykle Firebase przechowuje wyświetlaną nazwę przy pierwszym logowaniu się użytkownika w Apple. Możesz to uzyskać za pomocą current_user().display_name(). Jeśli jednak zdarzyło Ci się zalogować użytkownika w aplikacji wcześniej za pomocą usługi Apple, ale nie za pomocą Firebase, Apple nie udostępni Firebase jego wyświetlanej nazwy.

Dalsze kroki

Gdy użytkownik loguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z danymi logowania (nazwa użytkownika i hasło, numer telefonu lub informacje o dostawcy uwierzytelniania). Nowe konto będzie przechowywane jako część Twojego projektu Firebase i będzie używane do identyfikowania użytkowników we wszystkich aplikacjach w Twoim projekcie niezależnie od tego, jak użytkownik się loguje.

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

W Bazie danych czasu rzeczywistego Firebase i regułach zabezpieczeń Cloud Storage możesz uzyskać ze zmiennej uwierzytelniania unikalny identyfikator zalogowanego użytkownika i za jego pomocą kontrolować, do jakich danych użytkownik ma dostęp.