Save the date - Google I/O returns May 18-20. Register to get the most out of the digital experience: Build your schedule, reserve space, participate in Q&As, earn Google Developer profile badges, and more. Register now
Эта страница переведена с помощью Cloud Translation API.
Switch to English

Аутентификация с помощью Apple и C ++

Вы можете позволить своим пользователям проходить аутентификацию в Firebase с помощью своего Apple ID, используя Firebase SDK для выполнения сквозного потока входа OAuth 2.0.

Прежде чем вы начнете

Чтобы войти в систему пользователей с помощью Apple, сначала настройте Вход с помощью Apple на сайте разработчика Apple, а затем включите Apple в качестве поставщика входа для вашего проекта Firebase.

Присоединяйтесь к программе разработчиков Apple

Вход с помощью Apple может быть настроен только участниками программы Apple Developer Program .

Настроить вход через Apple

Apple Sign In должен быть включен и правильно настроен в вашем проекте Firebase. Конфигурация различается для разных платформ Android и iOS. Пожалуйста, следуйте разделу «Настроить вход с помощью Apple» в руководствах iOS и / или Android, прежде чем продолжить.

Включить Apple в качестве поставщика услуг входа

  1. В консоли Firebase откройте раздел Auth . На вкладке Метод входа включите поставщика Apple .
  2. Настройте параметры поставщика Apple Sign-in:
    1. Если вы развертываете свое приложение только на iOS, вы можете оставить поля Service ID, Apple Team ID, private key и key ID пустыми.
    2. Для поддержки на устройствах Android:
      1. Добавьте Firebase в свой проект Android . Обязательно зарегистрируйте подпись SHA-1 вашего приложения при настройке приложения в консоли Firebase.
      2. В консоли Firebase откройте раздел Auth . На вкладке Метод входа включите поставщика Apple . Укажите идентификатор службы, созданный в предыдущем разделе. Кроме того, в разделе конфигурации потока кода OAuth укажите свой Apple Team ID, а также закрытый ключ и идентификатор ключа, которые вы создали в предыдущем разделе.

Соблюдать требования Apple к анонимности данных

Вход с помощью Apple дает пользователям возможность анонимизировать свои данные, включая адрес электронной почты, при входе в систему. Пользователи, выбравшие этот вариант, имеют адреса электронной почты с доменом privaterelay.appleid.com . Когда вы используете Вход с Apple в своем приложении, вы должны соблюдать все применимые политики или условия Apple для разработчиков в отношении этих анонимных идентификаторов Apple ID.

Это включает получение любого необходимого согласия пользователя перед тем, как вы свяжете любую прямую идентифицирующую личную информацию с анонимным идентификатором Apple ID. При использовании аутентификации Firebase это может включать в себя следующие действия:

  • Свяжите адрес электронной почты с анонимным Apple ID или наоборот.
  • Свяжите номер телефона с анонимным Apple ID или наоборот
  • Свяжите неанонимные учетные данные соцсетей (Facebook, Google и т. Д.) С анонимным идентификатором Apple ID или наоборот.

Приведенный выше список не является исчерпывающим. См. Лицензионное соглашение программы Apple Developer в разделе «Членство» вашей учетной записи разработчика, чтобы убедиться, что ваше приложение соответствует требованиям Apple.

Доступ к классу firebase::auth::Auth

Класс Auth является шлюзом для всех вызовов API.
  1. Добавьте файлы заголовков Auth и App:
    #include "firebase/app.h"
    #include "firebase/auth.h"
    
  2. В вашем коде инициализации создайте класс 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. firebase::auth::Auth класс firebase::auth::Auth для своего firebase::App . Между App и Auth существует взаимно однозначное соответствие.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

Управляйте входом с помощью Firebase SDK

Процесс входа в систему с помощью Apple зависит от платформ iOS и Android.

На iOS

Аутентифицируйте своих пользователей с помощью Firebase с помощью SDK Apple Sign In Objective-C, вызываемого из вашего кода C ++.

  1. Для каждого запроса на вход сгенерируйте случайную строку - nonce - которую вы будете использовать, чтобы убедиться, что полученный вами идентификатор идентификатора был предоставлен специально в ответ на запрос аутентификации вашего приложения. Этот шаг важен для предотвращения атак повторного воспроизведения.

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

    Вы отправите SHA256-хэш одноразового номера с вашим запросом на вход, который Apple передаст без изменений в ответе. Firebase проверяет ответ, хешируя исходный одноразовый номер и сравнивая его со значением, переданным Apple.

  2. Запустите процесс входа Apple, включая в свой запрос хэш SHA256 одноразового номера и класс делегата, который будет обрабатывать ответ Apple (см. Следующий шаг):

      - (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. Обрабатывайте ответ Apple в своей реализации ASAuthorizationControllerDelegate`. Если вход был успешным, используйте токен идентификатора из ответа Apple с нехешированным значением nonce для аутентификации с помощью 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. Используйте полученную строку токена и оригинальный одноразовый номер, чтобы создать учетные данные Firebase и войти в Firebase.

    firebase::auth::OAuthProvider::GetCredential(
            /*provider_id=*/"apple.com", token, nonce,
            /*access_token=*/nullptr);
    
    firebase::Future<firebase::auth::User*> result =
        auth->SignInWithCredential(credential);
    
  5. Тот же шаблон можно использовать с Reauthenticate который можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему.

    firebase::Future<firebase::auth::SignInResult> result =
        user->Reauthenticate(credential);
    
  6. Тот же шаблон можно использовать для привязки учетной записи с помощью Apple Sign In. Однако вы можете столкнуться с ошибкой, если существующая учетная запись Firebase уже связана с учетной записью Apple, с которой вы пытаетесь установить связь. Когда это произойдет, в будущем будет возвращен статус kAuthErrorCredentialAlreadyInUse а объект UserInfo SignInResult может содержать действительный updated_credential . Эти учетные данные можно использовать для входа в учетную запись, связанную с Apple, через SignInWithCredential без необходимости создавать еще один токен входа Apple и одноразовый номер.

    Обратите внимание, что вы должны использовать LinkAndRetrieveDataWithCredential чтобы эта операция содержала учетные данные, поскольку updated_credential является членом объекта SignInResult.UserInfo .

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

На Android

На Android аутентифицируйте своих пользователей с помощью Firebase, интегрировав общий веб-вход OAuth в свое приложение с помощью Firebase SDK, чтобы выполнить сквозной процесс входа.

Чтобы обработать входной поток с помощью Firebase SDK, выполните следующие действия:

  1. Создайте экземпляр FederatedOAuthProviderData настроенный с идентификатором поставщика, подходящим для Apple.

    firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
    
  2. Необязательно: укажите дополнительные области OAuth 2.0 помимо значений по умолчанию, которые вы хотите запросить у поставщика проверки подлинности.

    provider_data.scopes.push_back("email");
    provider_data.scopes.push_back("name");
    
  3. Необязательно: если вы хотите отображать экран входа Apple на языке, отличном от английского, установите параметр locale . См. Документацию по входу с помощью Apple, чтобы узнать о поддерживаемых региональных стандартах.

    // Localize to French.
    provider_data.custom_parameters["language"] = "fr";
    ```
    
  4. После настройки данных вашего провайдера используйте их для создания FederatedOAuthProvider.

    // Construct a FederatedOAuthProvider for use in Auth methods.
    firebase::auth::FederatedOAuthProvider provider(provider_data);
    
  5. Выполните аутентификацию с помощью Firebase, используя объект поставщика аутентификации. Обратите внимание, что, в отличие от других операций FirebaseAuth, это будет управлять вашим пользовательским интерфейсом, открывая веб-представление, в котором пользователь может ввести свои учетные данные.

    Чтобы начать процесс входа, позвоните в signInWithProvider :

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

    После этого ваше приложение может подождать или зарегистрировать обратный вызов в Future .

  6. Тот же шаблон можно использовать с ReauthenticateWithProvider который можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему.

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

    После этого ваше приложение может подождать или зарегистрировать обратный вызов в Future .

  7. Кроме того, вы можете использовать linkWithCredential() для привязки различных поставщиков удостоверений к существующим учетным записям.

    Обратите внимание, что Apple требует, чтобы вы получили явное согласие пользователей, прежде чем связывать их учетные записи Apple с другими данными.

    Например, чтобы связать учетную запись Facebook с текущей учетной записью Firebase, используйте токен доступа, который вы получили при входе пользователя в Facebook:

    // 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);
    

Войти с помощью Apple Notes

В отличие от других поставщиков, поддерживаемых Firebase Auth, Apple не предоставляет URL-адрес фотографии.

Кроме того, когда пользователь решает не делиться своей электронной почтой с приложением, Apple предоставляет уникальный адрес электронной почты для этого пользователя (в форме xyz@privaterelay.appleid.com ), которым он делится с вашим приложением. Если вы настроили частную службу ретрансляции электронной почты, Apple пересылает электронные письма, отправленные на анонимный адрес, на реальный адрес электронной почты пользователя.

Apple предоставляет приложениям такую ​​информацию, как отображаемое имя, только при первом входе в систему. Обычно Firebase сохраняет отображаемое имя при первом getCurrentUser().getDisplayName() пользователя в систему Apple, что можно получить с помощью getCurrentUser().getDisplayName() . Однако, если вы ранее использовали Apple для входа пользователя в приложение без использования Firebase, Apple не предоставит Firebase отображаемое имя пользователя.

Следующие шаги

После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, связанная с учетными данными, то есть с именем пользователя и паролем, номером телефона или информацией о провайдере аутентификации, с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении в вашем проекте, независимо от того, как пользователь входит в систему.

В своих приложениях вы можете получить основную информацию профиля пользователя из объекта firebase :: auth :: user. См. Управление пользователями .

В своей базе данных Firebase Realtime и правилах безопасности облачного хранилища вы можете получить уникальный идентификатор пользователя вошедшего в систему из переменной auth и использовать его для управления данными, к которым пользователь может получить доступ.