Аутентификация пользователей с помощью «Войти через Google»

Sign in with Google помогает быстро интегрировать аутентификацию пользователя с вашим приложением Android. Пользователи могут использовать свои учетные записи Google для входа в ваше приложение, предоставления согласия и безопасного обмена информацией своего профиля с вашим приложением. Библиотека Credential Manager Jetpack для Android делает эту интеграцию гладкой, предлагая единообразный опыт на всех устройствах Android с использованием единого API.

В этом документе описывается, как реализовать функцию «Войти через Google» в приложениях Android, как настроить пользовательский интерфейс кнопки «Войти через Google» и как настроить оптимизированные для приложения возможности регистрации и входа в одно касание. Для плавной миграции устройств функция «Войти через Google» поддерживает автоматический вход, а ее кроссплатформенность для Android, iOS и веб-поверхностей помогает вам обеспечить доступ для входа в приложение на любом устройстве. Если вы используете аутентификацию Firebase для своего приложения, вы можете узнать больше об интеграции функции «Войти через Google» и диспетчера учетных данных в их руководстве «Аутентификация через Google на Android» .

Чтобы настроить вход через Google, выполните следующие два основных шага:

Настройте вход с помощью Google в качестве опции для нижнего листа пользовательского интерфейса Credential Manager . Его можно настроить для автоматического запроса пользователя на вход. Если вы внедрили ключи доступа или пароли , вы можете одновременно запросить все соответствующие типы учетных данных, чтобы пользователю не приходилось запоминать опцию, которую он использовал ранее для входа.

Нижний лист менеджера учетных данных
Рисунок 1. Пользовательский интерфейс выбора учетных данных нижнего листа диспетчера учетных данных

Добавьте кнопку «Войти через Google» в пользовательский интерфейс вашего приложения . Кнопка «Войти через Google» предлагает пользователям упрощенный способ использования существующих учетных записей Google для регистрации или входа в приложения Android. Пользователи нажмут кнопку «Войти через Google», если они отклонят нижний пользовательский интерфейс или если они явно хотят использовать свою учетную запись Google для регистрации и входа. Для разработчиков это означает более простую регистрацию пользователей и снижение трения во время регистрации.

Анимация, демонстрирующая процесс входа через Google
Рисунок 2. Пользовательский интерфейс кнопки «Войти с помощью Google» диспетчера учетных данных

В этом документе объясняется, как интегрировать кнопку «Войти через Google» и диалоговое окно нижней страницы с API диспетчера учетных данных с помощью вспомогательной библиотеки Google ID .

Настройте свой проект

  1. Откройте свой проект в или создайте проект, если у вас его еще нет.
  2. На , убедитесь, что вся информация является полной и точной.
    1. Убедитесь, что вашему приложению назначены правильное имя приложения, логотип приложения и домашняя страница приложения. Эти значения будут представлены пользователям на экране согласия «Войти с Google» при регистрации и на экране «Сторонние приложения и службы» .
    2. Убедитесь, что вы указали URL-адреса политики конфиденциальности и условий обслуживания вашего приложения.
  3. В , создайте идентификатор клиента Android для вашего приложения, если у вас его еще нет. Вам нужно будет указать имя пакета вашего приложения и подпись SHA-1.
    1. Перейти к .
    2. Нажмите Создать клиента .
    3. Выберите тип приложения Android .
  4. В , создайте новый идентификатор клиента "Веб-приложение", если вы этого еще не сделали. Пока можете игнорировать поля "Авторизованные источники JavaScript" и "Авторизованные URI перенаправления". Этот идентификатор клиента будет использоваться для идентификации вашего внутреннего сервера при его взаимодействии со службами аутентификации Google.
    1. Перейти к .
    2. Нажмите Создать клиента .
    3. Выберите тип веб-приложения .

Объявить зависимости

В файле build.gradle вашего модуля объявите зависимости, используя последнюю версию Credential Manager :

dependencies {
  // ... other dependencies

  implementation "androidx.credentials:credentials:<latest version>"
  implementation "androidx.credentials:credentials-play-services-auth:<latest version>"
  implementation "com.google.android.libraries.identity.googleid:googleid:<latest version>"
}

Инициировать запрос на вход в Google

Чтобы начать реализацию, создайте запрос на вход в Google . Используйте GetGoogleIdOption для получения токена Google ID пользователя.

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Сначала проверьте, есть ли у пользователя какие-либо учетные записи, которые ранее использовались для входа в ваше приложение, вызвав API с параметром setFilterByAuthorizedAccounts , установленным на true . Пользователи могут выбирать между доступными учетными записями для входа.

Если нет доступных авторизованных аккаунтов Google, пользователю следует предложить зарегистрироваться с помощью любого из доступных аккаунтов. Чтобы сделать это, предложите пользователю снова вызвать API и установить setFilterByAuthorizedAccounts на false . Узнайте больше о sign up .

Включить автоматический вход для повторных пользователей (рекомендуется)

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

Чтобы включить автоматический вход, используйте setAutoSelectEnabled(true) . Автоматический вход возможен только при соблюдении следующих критериев:

  • Запросу соответствуют одни учетные данные, которые могут быть учетной записью Google или паролем, и эти учетные данные соответствуют учетной записи по умолчанию на устройстве Android.
  • Пользователь явно не вышел из системы.
  • Пользователь не отключил автоматический вход в настройках своего аккаунта Google .
val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

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

Установите одноразовый номер для повышения безопасности

Чтобы улучшить безопасность входа и избежать атак повторного воспроизведения, добавьте setNonce , чтобы включить nonce в каждый запрос. Узнайте больше о создании nonce .

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(true)
  .setServerClientId(WEB_CLIENT_ID)
  .setAutoSelectEnabled(true)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Создайте поток «Войти через Google»

Ниже приведены шаги по настройке входа через Google:

  1. Создайте экземпляр GetCredentialRequest , затем добавьте ранее созданный googleIdOption с помощью addCredentialOption() для получения учетных данных.
  2. Передайте этот запрос вызову getCredential() (Kotlin) или getCredentialAsync() (Java) для получения доступных учетных данных пользователя.
  3. После успешного выполнения API извлеките CustomCredential , содержащий результат для данных GoogleIdTokenCredential .
  4. Тип для CustomCredential должен быть равен значению GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL . Преобразуйте объект в GoogleIdTokenCredential с помощью метода GoogleIdTokenCredential.createFrom .
  5. Если преобразование прошло успешно, извлеките идентификатор GoogleIdTokenCredential , проверьте его и выполните аутентификацию учетных данных на своем сервере.

  6. Если преобразование завершается ошибкой GoogleIdTokenParsingException , возможно, вам придется обновить версию библиотеки «Войти через Google» .

  7. Отслеживайте любые нераспознанные пользовательские типы учетных данных.

val request: GetCredentialRequest = Builder()
  .addCredentialOption(googleIdOption)
  .build()

coroutineScope.launch {
  try {
    val result = credentialManager.getCredential(
      request = request,
      context = activityContext,
    )
    handleSignIn(result)
  } catch (e: GetCredentialException) {
    handleFailure(e)
  }
}

fun handleSignIn(result: GetCredentialResponse) {
  // Handle the successfully returned credential.
  val credential = result.credential

  when (credential) {

    // Passkey credential
    is PublicKeyCredential -> {
      // Share responseJson such as a GetCredentialResponse on your server to
      // validate and authenticate
      responseJson = credential.authenticationResponseJson
    }

    // Password credential
    is PasswordCredential -> {
      // Send ID and password to your server to validate and authenticate.
      val username = credential.id
      val password = credential.password
    }

    // GoogleIdToken credential
    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract the ID to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
          // You can use the members of googleIdTokenCredential directly for UX
          // purposes, but don't use them to store or control access to user
          // data. For that you first need to validate the token:
          // pass googleIdTokenCredential.getIdToken() to the backend server.
          GoogleIdTokenVerifier verifier = ... // see validation instructions
          GoogleIdToken idToken = verifier.verify(idTokenString);
          // To get a stable account identifier (e.g. for storing user data),
          // use the subject ID:
          idToken.getPayload().getSubject()
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      } else {
        // Catch any unrecognized custom credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

    else -> {
      // Catch any unrecognized credential type here.
      Log.e(TAG, "Unexpected type of credential")
    }
  }
}

Активировать кнопку «Войти с помощью Google»

Чтобы активировать кнопку «Войти через Google», используйте GetSignInWithGoogleOption вместо GetGoogleIdOption :

val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption.Builder()
  .setServerClientId(WEB_CLIENT_ID)
  .setNonce(<nonce string to use when generating a Google ID token>)
  .build()

Обработайте возвращенный GoogleIdTokenCredential , как описано в следующем примере кода.

fun handleSignIn(result: GetCredentialResponse) {
  // Handle the successfully returned credential.
  val credential = result.credential

  when (credential) {
    is CustomCredential -> {
      if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        try {
          // Use googleIdTokenCredential and extract id to validate and
          // authenticate on your server.
          val googleIdTokenCredential = GoogleIdTokenCredential
            .createFrom(credential.data)
        } catch (e: GoogleIdTokenParsingException) {
          Log.e(TAG, "Received an invalid google id token response", e)
        }
      }
      else -> {
        // Catch any unrecognized credential type here.
        Log.e(TAG, "Unexpected type of credential")
      }
    }

    else -> {
      // Catch any unrecognized credential type here.
      Log.e(TAG, "Unexpected type of credential")
    }
  }
}

После создания запроса на вход через Google запустите процесс аутентификации аналогично тому, как описано в разделе «Вход через Google» .

Включить регистрацию для новых пользователей (рекомендуется)

Вход через Google — это самый простой способ для пользователей создать новую учетную запись в вашем приложении или сервисе всего за несколько нажатий.

Если сохраненные учетные данные не найдены (нет учетных записей Google, возвращенных getGoogleIdOption ), предложите пользователю зарегистрироваться. Сначала проверьте, setFilterByAuthorizedAccounts(true) чтобы узнать, существуют ли какие-либо ранее использованные учетные записи. Если ничего не найдено, предложите пользователю зарегистрироваться с помощью своей учетной записи Google с помощью setFilterByAuthorizedAccounts(false)

Пример:

val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
  .setFilterByAuthorizedAccounts(false)
  .setServerClientId(WEB_CLIENT_ID)
  .build()

После создания запроса на регистрацию Google запустите поток аутентификации. Если пользователи не хотят использовать Sign in with Google для регистрации, рассмотрите возможность оптимизации вашего приложения для автозаполнения . После того как ваш пользователь создаст учетную запись, рассмотрите возможность регистрации его в ключах доступа в качестве последнего шага к созданию учетной записи.

Выполнить выход из системы

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

Поставщик учетных данных мог сохранить активный сеанс учетных данных и использовать его для ограничения вариантов входа для будущих вызовов get-credential. Например, он может отдать приоритет активным учетным данным над любыми другими доступными учетными данными. Когда ваш пользователь явно выходит из вашего приложения и для того, чтобы получить целостные варианты входа в следующий раз, вы должны вызвать этот API, чтобы поставщик мог очистить любой сохраненный сеанс учетных данных.