Use o cliente de login com um toque para pedir permissão ao usuário para recuperar uma das credenciais que ele usou 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 salva com o Google usando o preenchimento automático do Chrome, do Android ou do Smart Lock para senhas.
Quando as credenciais são recuperadas, você pode usá-las para fazer login do usuário no seu app sem problemas.
Se o usuário não tiver salvo nenhuma credencial, nenhuma interface será apresentada, e você poderá oferecer a experiência normal de logout.
Onde devo usar o login com um toque?
Se o app exigir que os usuários façam login, mostre a interface do login com 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 interface do login com um toque pode ser configurada para mostrar apenas as credenciais que o usuário usou anteriormente para fazer login, ela pode ser um lembrete para usuários que fazem login com pouca frequência de como fizeram login da última vez e evitar que eles criem novas contas acidentalmente com seu app.
Se o login for opcional para seu app, considere usar o login com um toque em qualquer tela que tenha uma experiência aprimorada pelo login. Por exemplo, se os usuários puderem navegar pelo conteúdo com seu app enquanto estiverem desconectados, mas só puderem postar comentários ou adicionar itens a um carrinho de compras depois de fazer login, esse seria um contexto sensato para o login com um toque.
Os apps com login opcional também precisam usar o login com um toque nas telas de login, pelos motivos mencionados acima.
Antes de começar
- Configure seu projeto do console de APIs do Google e projeto do Android conforme descrito em Introdução ao 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 após fazer login.
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 salvas, Contas do Google salvas ou ambos. Recomendamos oferecer suporte aos dois para permitir 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 usar o login com senha, use setPasswordRequestOptions() para ativar as solicitações de credenciais de senha.
Se o app usar o Login do Google, use setGoogleIdTokenRequestOptions() para ativar e configurar as solicitações de token de ID do Google:
Defina o ID do cliente do servidor como o ID criado no console de APIs do Google. Observação: este é o ID do cliente do servidor, não o ID do cliente do Android.
Configure o cliente para filtrar por contas autorizadas. Quando você ativa essa opção, o cliente de login com um toque só pede que os usuários façam login no seu app com as Contas do Google que já usaram. Isso pode ajudar os usuários a fazer login com sucesso quando não têm certeza se já têm uma conta ou qual Conta do Google usaram, e impede que eles criem novas contas acidentalmente com seu app.
Se você quiser fazer login dos usuários automaticamente quando possível, ative o recurso com
setAutoSelectEnabled(). O login automático é possível quando os critérios abaixo 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 seja opcional, recomendamos que você considere usar um nonce para melhorar a segurança do login e evitar ataques de repetição. Use setNonce para incluir um nonce em cada solicitação. Consulte a seção Obter um nonce do SafetyNet para sugestões e mais detalhes sobre como gerar um 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(); // ... } // ... }
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 há um usuário conectado
Se a atividade puder ser usada por um usuário conectado ou desconectado, verifique o status do usuário antes de mostrar a interface do login com um toque.
Você também precisa acompanhar se o usuário já recusou o login com um toque fechando o aviso ou tocando fora dele. Isso pode ser tão simples quanto uma propriedade booleana da sua atividade. Consulte Parar de mostrar a interface do login com um toque abaixo.
3. Mostrar a interface do 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 do cliente e anexe listeners à Task que ele retorna. Os apps geralmente fazem isso no método onCreate() da atividade ou após transições de tela ao usar uma arquitetura de atividade única.
O cliente de login com um toque vai chamar o listener de sucesso se o usuário tiver credenciais salvas para seu app. No listener de sucesso, receba a intent pendente do resultado da Task e transmita-a para startIntentSenderForResult() para iniciar a interface do login com um toque.
Se o usuário não tiver credenciais salvas, o cliente de login com um toque vai chamar o listener de falha. Nesse caso, nenhuma ação é necessária: você pode simplesmente continuar apresentando a experiência de logout do app. No entanto, se você oferece suporte à inscrição com um toque, pode iniciar esse fluxo aqui para uma experiência de criação de conta perfeita. 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 ao aviso de login com um toque será informada ao seu app usando o método onActivityResult() da atividade. Se o usuário escolher fazer login, o resultado será uma credencial salva. Se o usuário recusar o login, fechando a interface do login com um toque ou tocando fora dela, o resultado será retornado com o código RESULT_CANCELED. Seu app precisa processar as duas possibilidades.
Fazer login com credenciais recuperadas
Se o usuário escolher compartilhar credenciais com seu app, você poderá recuperá-las transmitindo os dados da intent de onActivityResult() para o método getSignInCredentialFromIntent() do cliente de login com um toque. A credencial terá uma propriedade googleIdToken não nula se o usuário compartilhar 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-o para fazer login da mesma forma que faria se o usuário os tivesse fornecido manualmente.
Se as credenciais da Conta do Google forem recuperadas, use o token de ID para autenticar com o back-end. Se você tiver escolhido usar um nonce para evitar ataques de repetição, 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 interface do login com um toque
Se o usuário recusar 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 do login com um toque para não incomodar os usuários com avisos repetidos. O exemplo a seguir realiza essa ação definindo uma propriedade na atividade, que ela usa para determinar se deve oferecer o login com um toque 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 de avisos de login com um toque. Se você não fizer isso e um usuário cancelar vários avisos seguidos, o cliente de login com um toque não vai mostrar o aviso 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 fizer logout do seu app, chame o método signOut() do cliente de login com um toque.
A chamada 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 fizerem logout do seu app, o estado de autenticação de todas as APIs dos serviços do Google Play que você usa também seja redefinido.
Próximas etapas
Se você configurou o cliente de login com um toque para recuperar credenciais do Google, seu app agora pode receber tokens de ID do Google que representam as Contas do Google dos usuários. Saiba como usar esses tokens no back-end.
Se você oferece suporte ao Login do Google, também pode usar o cliente de login com um toque para adicionar fluxos de criação de contas sem problemas ao seu app.