Firebase Authentication: autentique com Google no Android
8 min8 minutos de leitura
8 min8 minutos de leitura
Autor(a)
Alex Felipe
Alex é instrutor e desenvolvedor e possui experiência em Java, Kotlin, Android. Atualmente cria conteúdo no canal https://www.youtube.com/@AlexFelipeDev.
Inscreva-se em nossa Newsletter
Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.
O projeto fornecido não acompanha o arquivo de integração com o Firebase, o google-services.json. Isso significa que ao rodar o App, o Android Studio vai indicar a ausência do arquivo e não vai executar.
Para resolver o problema, você precisa ter ou registrar um App para Android no console do Firebase com o pacote br.com.alura.aluraesporte. Então, basta apenas baixar o arquivo e adicionar dentro do módulo app do projeto. Ao rodar, deve apresentar uma tela similar a esta:
O Firebase Authentication permite a autenticação através de vários provedores, neste projeto, utilizamos o provedor de e-mail e senha. Isso significa que para usar outro provedor, é necessário realizar os mesmos passos:
Para pegar a impressão digital (fingerprint), você pode considerar qualquer uma das alternativas da documentação. Dentre elas, costumo usar a task do gradle signingReport que pode ser executada diretamente no projeto, o resultado é similar a este:
Habilitar o provedor do Google no console do Firebase
Observe que no campo de e-mail de suporte do projeto, você precisa colocar o seu, nesse caso usei um e-mail que criei para o projeto do Firebase.
Com todos os passos realizados, podemos implementar o código para realizar a autenticação.
Adicionando o botão de autenticação com o Google
Ao adicionar provedores como Google, Facebook ou outros serviços que oferecem a autenticação por meio do protocolo oAuth2, precisamos seguir alguns padrões na interface de usuário.
No caso da autenticação do Google, temos esse botão específico para indicar que a autenticação será feita a partir dele:
Podemos adicionar esse botão a partir desta tag dentro ConstraintLayout do login.xml:
Mesmo tendo todo o padrão, podemos mudar o tamanho do botão, porém, precisamos seguir as limitações da Google, que oferece constantes via código fonte para isso:
Sendo o padrão o SIZE_STANDARD e as demais opções, SIZE_WIDE ou SIZE_ICON.
Se preferir o padrão, não é necessário o SIZE_STANDARD
Caso o padrão não seja seguido, provavelmente, o seu App não será publicado por não seguir o padrão da integração com o serviço da Google.
Configurando as opções de inscrição da Google
Ao autenticar com o provedor da Google, precisamos configurar as opções de inscrições para definir como será feita a autenticação como, por exemplo, exigindo o token id e e-mail do usuário ou usuária:
login_botao_signin_google.setOnClickListener {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
}
Abrindo a tela de autenticação com o Google
Com o GoogleSignInOptions configurado, podemos criar o cliente da Google (GoogleSignInClient) e abrir a tela de autenticação a partir de uma Intent:
login_botao_signin_google.setOnClickListener {
val gso =
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
val cliente = GoogleSignIn.getClient(requireContext(), gso)
startActivityForResult(cliente.signInIntent, RC_SIGN_IN_GOOGLE)
}
RC_SIGN_IN_GOOGLE é uma constante que pode ser qualquer valor inteiro, por exemplo, o 1.
Ao rodar o projeto e clicar no botão da Google, temos o seguinte resultado sem uma conta configurada:
Ao configurar uma conta da Google, o fluxo de autenticação apenas solicita a permissão de autorização das informações da conta:
Ao finalizar o cadastro ou clicar na sua conta, a autenticação é feita, porém, isso não é o suficiente para integrar com o serviço do Firebase Authentication.
Observe que fazemos a chamada a partir de uma Intent que espera um resultado, portanto, precisamos também sobrescrever o método onActivityResult().
Obtendo o resultado da autenticação pela Intent
A implementação é similar às demais Intents, verificamos se o código de resultado é sucesso e se o código da requisição é o mesmo que enviamos ao iniciar a Intent:
Então teremos o resultado e veremos o que acontece ao tentar autenticar pelo botão da Google:
if (resultCode == RESULT_OK && requestCode == RC_SIGN_IN_GOOGLE) {
val contaGoogle = GoogleSignIn.getSignedInAccountFromIntent(data).result
Log.i(TAG, "onActivityResult: conta google autenticada $contaGoogle")
}
O resultado deve ser similar a este:
2020-07-31 15:59:08.790 3380-3380/br.com.alura.aluraesporte I/ContentValues: onActivityResult: conta google autenticada com.google.android.gms.auth.api.signin.GoogleSignInAccount@9aba2bbc
Com essa resposta, conseguimos integrar o comportamento de inscrição com o provedor da Google! Porém, é necessário fazer mais um passo para vincular a conta da Google com o Firebase Authentication.
Vinculando a conta da Google com o Firebase Authentication
O vínculo da conta do Google com o Firebase Authentication precisa das credenciais do provedor da Google.
Para isso podemos usar o método estático getCredentials() da classe GoogleAuthProvider que recebe o um idToken e um accessToken da conta do Google.
contaGoogle?.let { conta ->
val credencial = GoogleAuthProvider.getCredential(conta.idToken, null)
}
Observe que apenas o idToken é o necessário para obter a credencial.
Em seguida, precisaremos de uma instância de FirebaseAuth para fazer o vínculo, para isso podemos utilizar o LoginViewModel que tem acesso ao FirebaseAuthRepository que, por sua vez, tem uma instância do FirebaseAuth:
classFirebaseAuthRepository(privateval firebaseAuth: FirebaseAuth) {
//membrosfunvinculaContaGoogle(credencial: AuthCredential) : LiveData<Resource<Boolean>> {
val liveData = MutableLiveData<Resource<Boolean>>()
firebaseAuth.signInWithCredential(credencial)
.addOnSuccessListener {
liveData.value = Resource(true)
}
.addOnFailureListener {
liveData.value = Resource(false, "Falha ao vincular conta com a Google")
}
return liveData
}
}
Note que a implementação é similar aos demais comportamentos feitos com o FirebaseAuth, ou seja, precisamos apenas delegar o retorno do LiveData para quem estiver chamando, seja no ViewModel:
Como, também, no Fragment de login para tomar a devida ação no caso de falha ou sucesso:
contaGoogle?.let { conta ->
val credencial = GoogleAuthProvider.getCredential(conta.idToken, null)
viewModel.vinculaContaGoogle(credencial)
.observe(viewLifecycleOwner, Observer {
it?.let { recurso ->
if(recurso.dado){
vaiParaListaProdutos()
} else {
val mensagem = recurso.erro ?: "Falha ao vincular com a conta Google"
view?.snackBar(mensagem)
}
}
})
}
Ao executar novamente, temos o seguinte resultado ao tentar logar com a conta Google:
Por ter logado uma vez, a configuração de autorização é armazenada no App. Portanto, para apresentar novamente o mesmo dialog que solicita a autenticação com uma conta Google, é necessário realizar alguns passos a mais.
Deslogando a conta Google
Para que a pessoa consiga autenticar com uma outra conta Google, podemos apenas apagar os dados do App ou reinstalá-lo. Porém, para uma melhor experiência de usuário(a), podemos realizar essa tarefa ao deslogar com o FirebaseAuth.
O processo de deslogar com a conta da Google exige uma instância de GoogleSignInClient, sendo assim, podemos criar uma extension function que permite ter acesso a essa referência para quem tem acesso a um Context: