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

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

Подготовка

  1. Добавьте Firebase в свой проект C++.
  2. Включите Google в качестве поставщика услуг входа для проекта Firebase:
    1. В консоли Firebase выберите Безопасность > Аутентификация.
    2. На вкладке Способ входа включите поставщика для входа через Google.
    3. Нажмите Сохранить.
  3. Обновите файл конфигурации Firebase.

    1. Когда в консоли Firebase появится запрос, скачайте обновленный файл конфигурации Firebase (google-services.json), в котором теперь содержится информация о клиенте OAuth, необходимая для входа с аккаунтом Google.

    2. Переместите обновленный файл конфигурации в проект Android Studio, заменив устаревший файл. (Подробнее о том, как добавить Firebase в проект для Android…

Как получить доступ к курсу firebase::auth::Auth

Класс Auth – это шлюз для всех вызовов API.
  1. Добавьте файлы заголовков Auth и App:
    #include <cassert>
    #include <cstdint>
    
    #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

  1. Следуйте инструкциям для Android и iOS+, чтобы получить токен идентификатора для входа в аккаунт Google.
  2. После того как пользователь успешно войдет в аккаунт, обменяйте токен идентификатора на учетные данные Firebase и выполните аутентификацию в Firebase с помощью этих учетных данных:
    firebase::auth::Credential credential =
        firebase::auth::GoogleAuthProvider::GetCredential(google_id_token,
                                                          nullptr);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
  3. Если в вашей программе есть цикл обновления, который выполняется регулярно (например, 30 или 60 раз в секунду), вы можете проверять результаты один раз за обновление с помощью Auth::SignInAndRetrieveDataWithCredentialLastResult:
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::AuthResult auth_result = *result.result();
        printf("Sign in succeeded for `%s`\n",
               auth_result.user.display_name().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }
    Если ваша программа управляется событиями, вы можете зарегистрировать обратный вызов в объекте Future.

Как зарегистрировать обратный вызов в Future

В некоторых программах есть Update функции, которые вызываются 30 или 60 раз в секунду. Например, многие игры работают по этой модели. Эти программы могут вызывать функции LastResult для опроса асинхронных вызовов. Однако если ваша программа управляется событиями, вам может быть удобнее зарегистрировать функции обратного вызова. Функция обратного вызова вызывается после завершения Future.
void OnCreateCallback(const firebase::Future<firebase::auth::User*>& result,
                      void* user_data) {
  // The callback is called when the Future enters the `complete` state.
  assert(result.status() == firebase::kFutureStatusComplete);

  // Use `user_data` to pass-in program context, if you like.
  MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data);

  // Important to handle both success and failure situations.
  if (result.error() == firebase::auth::kAuthErrorNone) {
    firebase::auth::User* user = *result.result();
    printf("Create user succeeded for email %s\n", user->email().c_str());

    // Perform other actions on User, if you like.
    firebase::auth::User::UserProfile profile;
    profile.display_name = program_context->display_name;
    user->UpdateUserProfile(profile);

  } else {
    printf("Created user failed with error '%s'\n", result.error_message());
  }
}

void CreateUser(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // `&my_program_context` is passed verbatim to OnCreateCallback().
  result.OnCompletion(OnCreateCallback, &my_program_context);
}
При желании функцию обратного вызова можно заменить лямбда-функцией.
void CreateUserUsingLambda(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // The lambda has the same signature as the callback function.
  result.OnCompletion(
      [](const firebase::Future<firebase::auth::User*>& result,
         void* user_data) {
        // `user_data` is the same as &my_program_context, below.
        // Note that we can't capture this value in the [] because std::function
        // is not supported by our minimum compiler spec (which is pre C++11).
        MyProgramContext* program_context =
            static_cast<MyProgramContext*>(user_data);

        // Process create user result...
        (void)program_context;
      },
      &my_program_context);
}

Дальнейшие действия

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

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

    firebase::auth::User user = auth->current_user();
    if (user.is_valid()) {
      std::string name = user.display_name();
      std::string email = user.email();
      std::string photo_url = user.photo_url();
      // The user's ID, unique to the Firebase project.
      // Do NOT use this value to authenticate with your backend server,
      // if you have one. Use firebase::auth::User::Token() instead.
      std::string uid = user.uid();
    }
  • В Firebase Realtime Database и Cloud Storage правилах безопасности можно получить уникальный идентификатор пользователя, выполнившего вход, из переменной auth и использовать его, чтобы контролировать, к каким данным у пользователя есть доступ.

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

Чтобы выйти из аккаунта пользователя, вызовите функцию SignOut():

auth->SignOut();