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

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

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

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

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

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

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

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

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

Прежде чем вы начнете

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

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

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

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

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

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

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

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

Ява

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

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

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

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

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

Клиент 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() вашей Activity. Если пользователь решил войти в систему, результатом будут сохраненные учетные данные. Если пользователь отказался войти в систему, либо закрыв пользовательский интерфейс 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, чтобы добавить в свое приложение беспрепятственный процесс создания учетной записи .