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 no seu app. Essas credenciais podem ser uma Conta do Google ou uma combinação de nome de usuário e senha salvas com o Google usando o Chrome, o preenchimento automático do Android ou o Smart Lock para senhas.
Quando as credenciais forem recuperadas, você poderá usá-las para fazer o login do usuário no seu app com facilidade.
Se o usuário não tiver salvo nenhuma credencial, nenhuma IU será exibida, e você poderá oferecer sua experiência normal sem login.
Onde devo usar o login com um toque?
Se o app exigir que os usuários façam login, mostre a IU de um toque na tela de login. Isso pode ser útil mesmo que você já tenha um botão "Fazer login com o Google": como a IU de um toque pode ser configurada para mostrar apenas as credenciais que o usuário usou anteriormente para fazer login, esse recurso pode ser um lembrete para os usuários que fizeram login com pouca frequência da última vez e evitar que eles criem novas contas acidentalmente com o app.
Se o login for opcional para o app, considere usar o login com um toque em qualquer tela que tenha uma experiência aprimorada com o login. Por exemplo, se os usuários puderem navegar pelo conteúdo do seu app sem fazer login, mas só puderem postar comentários ou adicionar itens a um carrinho de compras depois de fazer login, esse contexto seria adequado para o login com um toque.
Os apps opcionais de login também precisam usar o login com um toque na tela de login, pelos motivos acima.
Antes de começar
- Configure seu projeto do Console de APIs do Google e o projeto do Android, conforme descrito em Primeiros passos com o login com um toque.
- Se você oferece suporte ao login com senha, otimize seu app para preenchimento automático (ou use o Smart Lock para senhas) para que os usuários possam salvar as credenciais de senha depois de fazer login.
1. Configurar o cliente de login com um toque
É possível configurar o cliente de login com um toque para fazer login de usuários com senhas salvas, Contas do Google salvas ou ambos. É recomendável oferecer suporte a ambos para 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 as solicitações de credenciais de senha.
Se o app utiliza o Login do Google, use setGoogleIdTokenRequestOptions()
para ativar e configurar as solicitações do token de ID do Google:
Defina o ID do cliente do servidor como o ID que você criou no console de APIs do Google. Esse é o ID do cliente do seu servidor, não do Android.
Configurar o cliente para filtrar por contas autorizadas. Quando você ativa essa opção, o cliente de um toque solicita que os usuários façam login no seu app apenas com as Contas do Google já usadas. Isso ajuda os usuários a fazer login quando não sabem se já têm uma conta ou qual Conta do Google foi usada, além de evitar que eles criem novas contas acidentalmente.
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 quando os seguintes critérios são atendidos:- 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 isso seja opcional, recomendamos usar um valor de uso único para melhorar a segurança de login e evitar ataques repetidos. Use setNonce para incluir um valor de uso único em cada solicitação. Consulte a seção Receber um valor de uso único do SafetyNet para sugestões e outros detalhes 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 a atividade puder ser usada por um usuário conectado ou desconectado, verifique o status do usuário antes de exibir a IU de login com um toque.
Também verifique se o usuário já recusou o uso do login com um toque fechando a solicitação ou tocando fora dela. Isso pode ser tão simples quanto uma propriedade booleana da sua atividade. Consulte Parar de exibir a IU de um toque abaixo.
3. Exibir a IU de login com um toque
Se o usuário não estiver conectado e ainda não tiver recusado o login com um toque,
chame o método beginSignIn()
do objeto cliente e anexe listeners ao
Task
retornado. Os apps geralmente 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 credencial
salva para seu app. No listener de êxito, receba a intent pendente do
resultado Task
e transmita-a para startIntentSenderForResult()
para iniciar a
IU de login com um toque.
Se o usuário não tiver nenhuma credencial salva, o cliente de um toque chamará o listener de falhas. Nesse caso, nenhuma ação é necessária: você pode simplesmente continuar apresentando a experiência sem login do app. No entanto, se você aceita a inscrição com um toque, pode iniciar esse fluxo aqui para ter uma experiência perfeita de criação de conta. Veja mais informações em 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á informada ao app
usando o método onActivityResult()
da sua atividade. Se o usuário fizer login,
o resultado será uma credencial salva. Se o usuário se recusar a fazer login, seja
fechando a IU com um toque ou tocando fora dela, o resultado retornará com o
código RESULT_CANCELED
. Seu app precisa lidar com as duas possibilidades.
Fazer login com as credenciais recuperadas
Se o usuário compartilhar credenciais com seu app, será possível recuperá-las
transmitindo os dados da intent de onActivityResult()
para o método getSignInCredentialFromIntent()
do cliente de um toque. A credencial terá uma propriedade googleIdToken
não nula 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 tiver compartilhado uma senha salva.
Use a credencial para autenticar com o back-end do app.
- Se um par de nome de usuário e senha tiver sido recuperado, use-os para fazer login da mesma maneira que você faria se o usuário tivesse fornecido manualmente.
Se as credenciais da Conta do Google tiverem sido recuperadas, use o token de ID para autenticar com o back-end. Se você escolheu usar um valor de uso único para ajudar a evitar ataques repetitivos, verifique 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 IU de um toque
Se o usuário se recusar a fazer login, a chamada para getSignInCredentialFromIntent()
gerará uma ApiException
com um código de status CommonStatusCodes.CANCELED
.
Quando isso acontecer, desative temporariamente a IU de login com um toque para
não incomodar os usuários com solicitações repetidas. O exemplo a seguir faz
isso definindo uma propriedade na atividade, que ela usa para determinar se
o login com um toque será oferecido ao usuário. No entanto, você também pode salvar um valor em
SharedPreferences
ou usar outro método.
É importante implementar sua própria limitação de taxa para solicitações de login com um toque. Se você não fizer isso e o usuário cancelar várias solicitações seguidas, o cliente de um toque não vai enviar uma solicitação ao usuário nas 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 o logout
Quando um usuário sair do seu 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 saiam do seu app, o estado de autenticação de todas as APIs do Google Play Services usadas também será redefinido.
Próximas etapas
Se você configurou o cliente de um toque para recuperar credenciais do Google, seu app agora pode receber tokens de ID do Google que representam as Contas do Google dos seus usuários. Saiba como você pode usar esses tokens no back-end.
Se você aceita o Login do Google, também é possível usar o cliente de um toque para adicionar fluxos de criação de conta simples ao seu app.