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

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

В этом документе описано, как реализовать вход с помощью номера телефона, используя Firebase SDK.

Подготовка

  1. Добавьте Firebase в свой проект C++.
  2. Если вы ещё не подключили приложение к проекту Firebase, сделайте это в консоли Firebase.
  3. Ознакомьтесь с требованиями к платформе для входа с помощью номера телефона:
    • Вход с помощью номера телефона доступен только на мобильных платформах.
    • На устройствах iOS вход с помощью номера телефона требует наличия физического устройства и не работает на симуляторе.

Проблемы с безопасностью

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

Если в вашем приложении для входа используется номер телефона, предложите пользователям более безопасные способы входа и расскажите о рисках, связанных с использованием номера телефона.

Как включить вход с помощью номера телефона в проекте Firebase

Чтобы пользователи могли входить в аккаунт с помощью SMS, сначала включите в проекте Firebase метод входа с номером телефона:

  1. В консоли Firebase выберите Безопасность > Аутентификация.
  2. На вкладке Sign-in method (Способ входа) включите поставщика для входа с помощью Phone (Телефона).
  3. Настройте правило для регионов, в которые вы хотите разрешить или запретить отправку SMS. Правило для региона SMS помогает защитить приложения от злоупотреблений с помощью SMS. Для новых проектов политика по умолчанию не разрешает использование регионов.
    1. В консоли Firebase выберите Безопасность > Аутентификация > вкладка Настройки.
    2. В разделе Правила в отношении регионов хранения данных для SMS настройте правила в отношении регионов хранения данных для SMS.

Как начать получать уведомления APNs (платформы Apple)

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

Чтобы включить уведомления APNs для использования с Firebase Authentication:

  1. В Xcode включите push-уведомления для своего проекта.
  2. Загрузите сертификат APNs в Firebase. Если у вас ещё нет сертификата APNs, создайте его в Центре разработчиков Apple.

    1. В консоли Firebase выберите Настройки > Общие. Затем нажмите на вкладку Обмен сообщениями в облаке.
    2. Нажмите Загрузить сертификат для сертификата разработчика, производственного сертификата или обоих. Обязательно заполните как минимум одно из этих полей.
    3. Для каждого сертификата выберите файл .p12 и укажите пароль, если он есть. Убедитесь, что идентификатор пакета для этого сертификата совпадает с идентификатором пакета вашего приложения. Нажмите Сохранить.

Отправить код подтверждения на телефон пользователя.

Чтобы начать вход с номером телефона, покажите пользователю интерфейс, в котором он сможет ввести свой номер, а затем вызовите метод PhoneAuthProvider::VerifyPhoneNumber, чтобы Firebase отправил код аутентификации на телефон пользователя по SMS:

  1. Получить номер телефона пользователя.

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

  2. Вызовите функцию PhoneAuthProvider::VerifyPhoneNumber, передав ей номер телефона пользователя.
    class PhoneListener : public PhoneAuthProvider::Listener {
     public:
      ~PhoneListener() override {}
    
      void OnVerificationCompleted(PhoneAuthCredential credential) override {
        // Auto-sms-retrieval or instant validation has succeeded (Android only).
        // No need for the user to input the verification code manually.
        // `credential` can be used instead of calling GetCredential().
      }
    
      void OnVerificationFailed(const std::string& error) override {
        // Verification code not sent.
      }
    
      void OnCodeSent(const std::string& verification_id,
                      const PhoneAuthProvider::ForceResendingToken&
                          force_resending_token) override {
        // Verification code successfully sent via SMS.
        // Show the Screen to enter the Code.
        // Developer may want to save that verification_id along with other app states in case
        // the app is terminated before the user gets the SMS verification code.
      }
    };
    
    PhoneListener phone_listener;
    PhoneAuhtOptions options;
    options.timeout_milliseconds = kAutoVerifyTimeOut;
    options.phone_number = phone_number;
    PhoneAuthProvider& phone_provider = PhoneAuthProvider::GetInstance(auth);
    phone_provider->VerifyPhoneNumber(options, &phone_listener);
    Когда вы вызываете PhoneAuthProvider::VerifyPhoneNumber, Firebase,
    • (на iOS) отправляет в приложение push-уведомление без звука;
    • отправляет SMS-сообщение с кодом аутентификации на указанный номер телефона и передает идентификатор подтверждения в функцию завершения. Чтобы войти в аккаунт пользователя, вам понадобятся код и идентификатор подтверждения.
  3. Сохраните идентификатор проверки и восстановите его при загрузке приложения. Это позволит вам сохранить действительный идентификатор проверки, если приложение будет закрыто до того, как пользователь завершит процесс входа (например, при переключении на приложение для обмена SMS).

    Вы можете сохранить идентификатор подтверждения любым удобным способом. Если вы пишете код на кроссплатформенном фреймворке C++, он должен предоставлять уведомления о завершении и восстановлении работы приложения. В этих событиях можно сохранять и восстанавливать идентификатор проверки.

Если вызов VerifyPhoneNumber приводит к вызову OnCodeSent на вашем слушателе, вы можете предложить пользователю ввести код подтверждения, когда он получит его в SMS.

Если вызов VerifyPhoneNumber возвращает OnVerificationCompleted, значит автоматическая проверка прошла успешно и вы получили PhoneAuthCredential, который можно использовать описанными ниже способами.

Как войти в аккаунт с помощью кода подтверждения

После того как пользователь введет в приложении код подтверждения из SMS, выполните вход, создав объект PhoneAuthCredential на основе кода подтверждения и идентификатора проверки и передав этот объект в Auth::SignInWithCredential.

  1. Получите код подтверждения от пользователя.
  2. Создайте объект Credential на основе кода подтверждения и идентификатора подтверждения.
    PhoneAuthCredential credential = phone_auth_provider->GetCredential(
        verification_id_.c_str(), verification_code.c_str());
        
  3. Войдите в аккаунт пользователя с помощью объекта Credential:
    Future<User> future = auth_->SignInWithCredential(credential);
    future.OnCompletion(
        [](const Future<User*>& result, void*) {
          if (result.error() == kAuthErrorNone) {
            // Successful.
            // User is signed in.
            User user = *result.result();
    
            // This should display the phone number.
            printf("Phone number: %s", user.phone_number().c_str());
    
            // The phone number provider UID is the phone number itself.
            printf("Phone provider uid: %s", user.uid().c_str());
    
            // The phone number providerID is 'phone'
            printf("Phone provider ID: %s", user.provider_id().c_str());
          } else {
            // Error.
            printf("Sign in error: %s", result.error_message().c_str());
          }
        },
        nullptr);

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

После первого входа пользователя создается новый аккаунт, связанный с учетными данными, которые он использовал (именем пользователя и паролем, номером телефона или информацией поставщика услуг аутентификации). Этот новый аккаунт хранится в проекте 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();