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

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

Интерфейс входа в систему одним касанием

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ява

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. Проверьте наличие вошедшего пользователя.

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

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

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

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

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

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

Ява

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. Обработка ответа пользователя

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

Войдите с полученными учетными данными

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

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

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

Ява

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) {
                    // ...
                }
            }
        }
    }
    // ...
}

Прекратить отображение пользовательского интерфейса One Tap

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

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

Ява

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, чтобы добавить в свое приложение удобные процессы создания учетной записи .