Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

Аутентификация с использованием 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 и Apple. Прежде чем продолжить, следуйте разделу «Настройка входа с помощью Apple» в руководствах по платформам Apple и/или Android .

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

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

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

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

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

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

Приведенный выше список не является исчерпывающим. См. Лицензионное соглашение программы Apple Developer Program в разделе «Членство» вашей учетной записи разработчика, чтобы убедиться, что ваше приложение соответствует требованиям 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::App . Между App и Auth существует однозначное соответствие.
    firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
    

Обработка процесса входа с помощью Firebase SDK

Процесс входа в систему с Apple различается на платформах Apple и Android.

На платформах Apple

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

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

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

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

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

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

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