Fazer login dos usuários com as credenciais salvas

Use o cliente de login com um toque para solicitar permissão do usuário para recuperar uma das credenciais usadas anteriormente para fazer login em seu aplicativo. Esses as credenciais podem ser uma Conta do Google ou uma combinação de nome de usuário e senha salvaram no Google usando o Chrome, o preenchimento automático do Android ou o Smart Lock para Senhas.

interface de login com um toque

Quando as credenciais são recuperadas com sucesso, você pode usá-las para fazer o login do usuário no seu app.

Se o usuário não tiver salvado nenhuma credencial, nenhuma interface será apresentada, e você poderá fornecem sua experiência normal quando desconectado.

Onde devo usar o login com um toque?

Se o app exige que os usuários façam login, mostre a interface de um toque no login tela. Isso pode ser útil mesmo se você já tiver uma opção "Fazer login com o Google" porque a interface de um toque pode ser configurada para mostrar apenas as credenciais que o usado anteriormente para fazer login, isso pode ser um lembrete para os usuários que o login da última vez e impedir que ele seja acidentalmente criar novas contas com seu app.

Se o login for opcional para seu app, use o login com um toque em qualquer tela que tem uma experiência aprimorada com o login. Por exemplo, se os usuários podem navegar pelo conteúdo com seu aplicativo quando estiver desconectado, mas só pode postar comentários ou adicionar itens no carrinho de compras após o login, esse seria um contexto sensível para Login com um toque.

Os apps opcionais de login também precisam usar o login com um toque nas telas de login. pelas razões mencionadas acima.

Antes de começar

1. Configurar o cliente de login com um toque

Você pode configurar o cliente de login com um toque para fazer login dos usuários com senhas, Contas do Google salvas ou qualquer um deles. É recomendável oferecer suporte aos dois ativar a criação de contas com um toque para novos usuários e o login automático ou com um toque; para o maior número possível de usuários recorrentes.

Se o app usa login com base em senha, use setPasswordRequestOptions() para ativar solicitações de credenciais de senha.

Caso seu app use o Login do Google, use setGoogleIdTokenRequestOptions() para ativar e configurar solicitações de token de ID do Google:

  • Defina o ID do cliente do servidor como o ID criado nas APIs do Google console do Cloud. Esse é o ID do cliente do seu servidor, não seu ID do cliente Android.

  • Configurar o cliente para filtrar por contas autorizadas Quando você ativa essa opção, o cliente de um toque só solicita que os usuários façam login no app com Contas do Google usadas anteriormente. Isso ajuda os usuários a assinar com sucesso quando não têm certeza se já têm uma conta ou quais Conta do Google usada pelo usuário e impede que os usuários criem novos contas com seu app.

  • Se você quiser que os usuários façam login automaticamente sempre que possível, ative o recurso com setAutoSelectEnabled(). O login automático é possível seguintes critérios:

    • O usuário tem exatamente uma credencial salva para o app. Ou seja, uma senha ou Conta do Google salva.
    • O usuário não desativou o login automático nas configurações da Conta do Google.
  • Embora opcional, recomendamos que você considere usar um valor de uso único para melhorar a segurança de login e evitar ataques repetidos. Usar setNonce incluir um valor de uso único em cada solicitação. Consulte SafetyNet Tenha um valor de uso único para sugestões e detalhes adicionais sobre como gerar um valor de uso único.

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

Kotlin

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. Verificar se um usuário fez login

Se sua atividade puder ser usada por um usuário conectado ou desconectado, marque o status do usuário antes de mostrar a interface de login com um toque.

Você também deve acompanhar se o usuário já recusou o uso Para fazer login com um toque, feche ou toque fora da solicitação. Isso pode ser tão simples quanto uma propriedade booleana da sua atividade. Consulte Parar de exibir a interface com um toque abaixo.

3. Mostrar a interface de login com um toque

Se o usuário não tiver feito login e ainda não tiver recusado o uso do login com um toque, chamar o método beginSignIn() do objeto cliente e anexar listeners ao Task que ela retorna. Normalmente, os apps fazem isso no método onCreate() da atividade. ou após as transições de tela ao usar uma arquitetura de atividade única.

O cliente de um toque vai chamar o listener de êxito se o usuário tiver alguma credenciais do seu app. No listener de sucesso, acesse a intent pendente de o resultado Task e transmita-o ao método startIntentSenderForResult() para iniciar o Interface de login com um toque.

Se o usuário não tiver nenhuma credencial salva, o cliente de um toque chamará o listener de falha. Nesse caso, nenhuma ação é necessária. Você pode simplesmente continuar apresentando a experiência do app sem fazer login. No entanto, se você oferece suporte para um toque inscrição, você pode iniciar esse fluxo aqui para uma criação de conta perfeita do usuário. Consulte Criar novas contas com um toque.

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());
            }
        });

Kotlin

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. Processar a resposta do usuário

A resposta do usuário à solicitação de login com um toque será enviada ao app usando o método onActivityResult() da atividade. Se o usuário fizer login, o resultado será uma credencial salva. Se o usuário se recusar a fazer login, ao fechar a interface de um toque ou tocar fora dela, o resultado retornará com a mensagem código RESULT_CANCELED. Seu app precisa lidar com as duas possibilidades.

Fazer login com credenciais recuperadas

Se o usuário tiver compartilhado credenciais com o app, você poderá recuperá-las transmitindo os dados de intent de onActivityResult() para a interface de usuário de um toque getSignInCredentialFromIntent(). A credencial terá um valor googleIdToken se o usuário tiver compartilhado uma credencial da Conta do Google com seu app ou uma propriedade password não nula se o usuário compartilhar uma senha salva.

Use a credencial para autenticar com o back-end do app.

  • Se um par de nome de usuário e senha for recuperado, use-os para fazer login da mesma forma como faria se o usuário as tivesse fornecido manualmente.
  • Se as credenciais da Conta do Google foram recuperadas, use o token de ID para autenticar com o back-end. Se você escolheu usar um valor de uso único para evitar a repetição os ataques verificam o valor da resposta no servidor de back-end. Consulte Autenticar com um back-end usando tokens de 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;
      }
  }
}

Kotlin

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

Parar de mostrar a interface de um toque

Se o usuário tiver recusado o login, a chamada para getSignInCredentialFromIntent() vai gerar uma ApiException com um código de status CommonStatusCodes.CANCELED. Quando isso acontecer, desative temporariamente a interface de login com um toque para não incomode os usuários com solicitações repetidas. O exemplo a seguir realiza isso definindo uma propriedade na atividade, que é usada para determinar se para oferecer ao usuário o login com um toque; No entanto, também é possível salvar um valor SharedPreferences ou use algum outro método.

É importante implementar sua própria limitação de taxa das solicitações de login com um toque. Se você não fizer isso e um usuário cancelar várias solicitações seguidas, o cliente de um toque não solicitará ao usuário as próximas 24 horas.

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;
      }
  }
}

Kotlin

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. Processar a saída

Quando um usuário sair do app, chame o método signOut() do cliente de um toque. Chamar signOut() desativa o login automático até que o usuário faça login novamente.

Mesmo que você não use o login automático, essa etapa é importante porque garante que, quando os usuários saírem do aplicativo, o estado de autenticação de qualquer As APIs do Google Play Services que você usa também são redefinidas.

Próximas etapas

Se você configurou o cliente de um toque para recuperar as credenciais do Google, seu app agora pode obter tokens de ID do Google que representam Contas do Google. Aprender como usar esses tokens no back-end.

Se você oferece suporte ao Login do Google, também pode usar o cliente de um toque para adicionar fluxos de criação de contas simples para seu app.