Авторизуйте пользователей, используя их сохраненные учетные данные.

Используйте клиент One Tap для входа в систему, чтобы запросить у пользователя разрешение на получение одних из учетных данных, которые он ранее использовал для входа в ваше приложение. Этими учетными данными может быть либо учетная запись Google, либо комбинация имени пользователя и пароля, сохраненная пользователем в Google с помощью Chrome, автозаполнения Android или Smart Lock для паролей.

Пользовательский интерфейс для входа в систему одним касанием

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

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

Где мне следует использовать вход в систему одним касанием?

Если ваше приложение требует от пользователей авторизации, отобразите интерфейс One Tap UI на экране входа в систему. Это может быть полезно, даже если у вас уже есть кнопка «Войти через Google»: поскольку интерфейс One Tap UI можно настроить так, чтобы он отображал только учетные данные, которые пользователь использовал для входа ранее, это может служить напоминанием пользователям, которые редко входят в систему, о том, как они входили в нее в прошлый раз, и предотвратить случайное создание ими новых учетных записей в вашем приложении.

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

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

Прежде чем начать

1. Настройте клиент для входа в систему One Tap.

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

Если ваше приложение использует вход по паролю, используйте функцию setPasswordRequestOptions() чтобы разрешить запросы учетных данных по паролю.

Если ваше приложение использует вход через Google, используйте функцию setGoogleIdTokenRequestOptions() для включения и настройки запросов токенов Google ID:

  • Установите идентификатор клиента сервера равным идентификатору, который вы создали в консоли Google API . Обратите внимание, что это идентификатор клиента вашего сервера, а не идентификатор вашего клиента Android.

  • Настройте клиент для фильтрации по авторизованным учетным записям. При включении этой опции клиент One Tap будет предлагать пользователям войти в ваше приложение только с помощью учетных записей Google, которые они уже использовали ранее. Это поможет пользователям успешно войти в систему, если они не уверены, есть ли у них уже учетная запись или какую именно учетную запись Google они использовали, а также предотвратит случайное создание новых учетных записей в вашем приложении.

  • Если вы хотите автоматически входить в систему пользователей, когда это возможно, включите эту функцию с помощью setAutoSelectEnabled() . Автоматический вход в систему возможен при выполнении следующих условий:

    • У пользователя сохранены только одни учетные данные для вашего приложения. То есть, один сохраненный пароль или одна сохраненная учетная запись Google.
    • Пользователь не отключил автоматический вход в систему в настройках своего аккаунта Google .
  • Хотя использование nonce необязательно, мы настоятельно рекомендуем рассмотреть возможность его применения для повышения безопасности входа в систему и предотвращения атак повторного воспроизведения. Используйте setNonce для включения nonce в каждый запрос. См. раздел SafetyNet « Получение nonce» для получения рекомендаций и дополнительной информации о генерации nonce.

Java

public class YourActivity extends AppCompatActivity {
  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signInRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signInRequest = BeginSignInRequest.builder()
              .setPasswordRequestOptions(PasswordRequestOptions.builder()
                      .setSupported(true)
                      .build())
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.default_web_client_id))
                      // Only show accounts previously used to sign in.
                      .setFilterByAuthorizedAccounts(true)
                      .build())
              // Automatically sign in when exactly one credential is retrieved.
              .setAutoSelectEnabled(true)
              .build();
      // ...
  }
  // ...
}

Котлин

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signInRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signInRequest = BeginSignInRequest.builder()
            .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
                .setSupported(true)
                .build())
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Only show accounts previously used to sign in.
                    .setFilterByAuthorizedAccounts(true)
                    .build())
            // Automatically sign in when exactly one credential is retrieved.
            .setAutoSelectEnabled(true)
            .build()
        // ...
    }
    // ...
}

2. Проверьте наличие авторизованного пользователя.

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

Также следует отслеживать, отказался ли пользователь от использования входа в систему одним касанием, закрыв окно запроса или коснувшись его. Это можно сделать с помощью простого логического свойства вашего Activity. (См. раздел «Прекратить отображение интерфейса входа в систему одним касанием» ниже.)

3. Отобразить пользовательский интерфейс входа в систему одним касанием.

Если пользователь не авторизован и еще не отказался от использования входа в систему одним касанием, вызовите метод beginSignIn() объекта клиента и прикрепите обработчики событий к возвращаемой им Task . Обычно приложения делают это в методе onCreate() Activity или после переходов между экранами при использовании архитектуры с одной Activity.

Клиент One Tap вызовет обработчик успешного выполнения, если у пользователя есть сохраненные учетные данные для вашего приложения. В обработчике успешного выполнения получите ожидающее намерение из результата Task и передайте его в startIntentSenderForResult() , чтобы запустить пользовательский интерфейс входа в One Tap.

Если у пользователя нет сохраненных учетных данных, клиент One Tap вызовет обработчик ошибки. В этом случае никаких действий не требуется: вы можете просто продолжить отображение страницы выхода из системы. Однако, если вы поддерживаете регистрацию в One Tap, вы можете запустить этот процесс здесь для беспроблемного создания учетной записи. См. раздел «Создание новых учетных записей в одно касание» .

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No saved credentials found. Launch the One Tap sign-up flow, or
                // do nothing and continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Котлин

oneTapClient.beginSignIn(signInRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0, null)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No saved credentials found. Launch the One Tap sign-up flow, or
        // do nothing and continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. Обработка ответа пользователя.

Ответ пользователя на запрос входа в систему One Tap будет передан в ваше приложение с помощью метода onActivityResult() вашего Activity. Если пользователь выбрал вход в систему, результатом будет сохранена учетная запись. Если пользователь отказался от входа в систему, закрыв интерфейс One Tap или коснувшись его вне, будет возвращен код RESULT_CANCELED . Ваше приложение должно обрабатывать обе возможности.

Войдите в систему, используя полученные учетные данные.

Если пользователь решил поделиться учетными данными с вашим приложением, вы можете получить их, передав данные намерения из метода onActivityResult() в метод getSignInCredentialFromIntent() клиента One Tap. Учетные данные будут иметь ненулевое свойство googleIdToken если пользователь поделился учетными данными учетной записи Google с вашим приложением, или ненулевое свойство password если пользователь поделился сохраненным паролем.

Используйте эти учетные данные для аутентификации на стороне бэкэнда вашего приложения.

  • Если была получена пара «имя пользователя и пароль», используйте её для входа в систему так же, как если бы пользователь ввёл её вручную.
  • Если были получены учетные данные учетной записи Google, используйте токен ID для аутентификации на вашем бэкэнде. Если вы выбрали использование nonce для предотвращения атак повторного воспроизведения, проверьте значение ответа на вашем бэкэнд-сервере. См. раздел «Аутентификация на бэкэнде с использованием токенов ID» .

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  String username = credential.getId();
                  String password = credential.getPassword();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  } else if (password != null) {
                      // Got a saved username and password. Use them to authenticate
                      // with your backend.
                      Log.d(TAG, "Got password.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Котлин

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    val username = credential.id
                    val password = credential.password
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        password != null -> {
                            // Got a saved username and password. Use them to authenticate
                            // with your backend.
                            Log.d(TAG, "Got password.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token or password!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
                }
            }
        }
    }
    // ...
}

Прекратить отображение интерфейса «Одно касание»

Если пользователь откажется от входа в систему, вызов метода getSignInCredentialFromIntent() вызовет ApiException со статусом CommonStatusCodes.CANCELED . В этом случае следует временно отключить интерфейс входа в систему одним касанием, чтобы не раздражать пользователей повторными запросами. В следующем примере это достигается путем установки свойства в Activity, которое используется для определения того, предлагать ли пользователю вход в систему одним касанием; однако вы также можете сохранить значение в SharedPreferences или использовать другой метод.

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

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Котлин

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

5. Обработка процедуры выхода из системы.

Когда пользователь выходит из вашего приложения, вызовите метод signOut() клиента One Tap. Вызов signOut() отключает автоматический вход в систему до тех пор, пока пользователь не войдет в систему снова.

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

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

Если вы настроили клиент One Tap для получения учетных данных Google, ваше приложение теперь может получать токены Google ID, представляющие учетные записи Google ваших пользователей. Узнайте, как использовать эти токены на бэкэнде .

Если вы поддерживаете вход через Google, вы также можете использовать клиент One Tap для добавления в ваше приложение удобных процессов создания учетных записей .