INTRODUZIONE
Qualsiasi applicazione che prevede la gestione di utenti pone come primo e fondamentale passo la loro creazione e gestione. Esistono varie metodologie per gestire la registrazione, da quella tradizionale tramite username e password oppure utilizzando l’autenticazione per conto terzi, ad esempio con piattaforme come Google, Facebook, Twitter, ecc…
Entrambe le scelte dal punto di vista dello sviluppatore sono assolutamente valide ma la seconda opzione offre una grande molteplicità di vantaggi tra i quali quelli di maggior interesse sono:
- Il più importante è senza dubbio quello di poter collezionare i dati utente come nome, email, ecc… che potranno essere utilizzati in futuro per fornire informazioni mirate, offerte personalizzate, ecc…
- Poter espandere il bacino di utenti, ad esempio nel caso di Facebook possiamo contare su creazione di commenti, post e condivisioni attraverso il social
- Incrementare il ranking SEO grazie alle condivisioni di Google+
- Per l’utente la registrazione diventa un processo semplice e veloce.
- Riduzione dello spam in quanto l’autenticazione attraverso un social network molto spesso è individuale e non permette account multipli.
- Ottenere dati meno “disonesti” dagli utenti registrati in quanto tramite una registrazione tradizionale molti utenti utilizzano finti indirizzi email o identificativi.
In questo articolo in particolare ci concentreremo sull’autenticazione integrando Google Sign-In.
Tutto il codice presentato è disponibile attraverso un’applicazione di esempio da me creata a questo indirizzo in modo tale che possa essere più semplice capire e provare quanto andremo ad analizzare.
Passiamo ai fatti
Il processo di integrazione si compone di 3 fasi fondamentali: preparazione SDK e Google repository, configurazione dell’app in Google Developer Console, autenticazione client utilizzando le api fornite.
Preparazione SDK e google repository
Google fornisce una SDK nativa per Android per gestire il login. Il primo passo è quello di scaricarla ed abilitarla tramite il tool SDK manager in Android Studio dal menu
Tools
-> SDK Manager
Nella sezione SDK Tools
verifichiamo che le voci Google Repository
e Google Play services
siano selezionate.
A questo punto possiamo aggiungere Google Play services al nostro progetto. Come primo passo assicuriamoci che il repository maven di google sia stato aggiunto al file build.gradle del progetto come indicato di seguito
allprojects { repositories { google() } }
mentre nel file build.gradle del modulo dell’app andiamo ad aggiungere le dipendenze al modulo
dependencies { ... implementation 'com.google.android.gms:play-services-auth:11.8.0' ... }
L’ultimo passo da compiere prima di passare al codice è quello di configurare il nostro progetto nella Google API console per abilitare il Sign-In.
configurazione google API console
In questa fase dovremo creare le Chiavi API necessarie per il login attraverso la Google API Console.
Come prima cosa dovrà essere creato un progetto e nella scheda Schermata consenso OAuth indichiamo il nome del progetto (valore obbligatorio) e a nostra discrezione le varie voci che ci vengono proposte. Fatto ciò nella scheda Credenziali scegliamo la voce ID client OAuth, come tipo di applicazione Android e proseguiamo con la creazione.
Nella pagina della configurazione della chiave dobbiamo ora definire i seguenti valori:
- Nome: indica il nome dell’ID client OAuth e possiamo inserire quello che più ci piace ad esempio “Client Debug Android”
- Nome e pacchetto: rappresenta l’application id che abbiamo scelto nella nostra applicazione android. Lo possiamo trovare nel file build.gradle nella proprietà
applicationId
o nel file Manifest.xml nell’elementomanifest
alla prorietàpackage
. Nel nostro esempio andremo ad indicare il valorecom.gmail.fattazzo.googlesignin.example
- Impronta digitale certificato SHA-1: per ottenere l’impronta valida per l’ambiente di debug possiamo sfruttare il keystore fornito da Android Studio in questo modo:
keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
keytool -exportcert -list -v -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore
* La password di default del keystore di debug èandroid
.
** La posizione del certificato di debug in Windows potrebbe variare in base alla versione del sistema operativo.
Inserite le 3 informazioni richieste salviamo e la configurazione della Chiave API risulta completata.
Quanto abbiamo visto è valido per la creazione di una chiave che può essere utilizzata solamente per il nostro ambiente di debug. Dovrà quindi essere creata nella stessa maniera una chiave di release che cambierà rispetto a quella precedente solamente nel valore dell’impronta SHA che potremo ricavare con il comando
keytool -list -v -keystore mystore.keystore
dove mystore.keystore è il certificato con il quale firmeremo l’app prima di aggiungerla nel Play Store.
integrazione google sign-in
Dopo la fase preliminare di configurazione possiamo finalmente passare alla creazione della nostra applicazione. La prima cosa da ricordare è quella di aggiungere il permesso INTERNET alla nostra applicazione nel file Manifest.xml in questo modo
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gmail.fattazzo.googlesignin.example"> <uses-permission android:name="android.permission.INTERNET" /> <application ... </application> </manifest>
Passo fondamentale ora è quello di inizializzare il client per effettuare le request dei dati utente. Di seguito riporto il codice per una request standard di Google Sing-In nella quale andremo a richiedere le informazioni base dell’account ( con GoogleSignInOptions.DEFAULT_SIGN_IN
) e l’email con l’opzione requestEmail
.
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)requestEmail().build() googleSignInClient = GoogleSignIn.getClient(this, options)
GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail().build(); googleSignInClient = GoogleSignIn.getClient(this, options);
Login
Posizioniamo il login button di Google nel layout della nostra activity
<com.google.android.gms.common.SignInButton android:id="@+id/signInButton" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Quello che dovremo fare ora è lanciare l’activity di Sing-In di Google rimanendo in attesa del risultato per ottenere le informazioni dell’account. Ecco il codice e gli eventi del processo di login:
1. Click button di Sing-In
@Click protected fun signInButtonClicked() { val signInIntent = googleSignInClient.signInIntent startActivityForResult(signInIntent, Companion.RC_SIGN_IN) }
@Click protected void signInButtonClicked() { Intent signInIntent = googleSignInClient.getSignInIntent(); startActivityForResult(signInIntent, RC_SIGN_IN); }
2. L’activity lanciata visualizzarà automaticamente un dialog contenente tutti gli account google configurati sul dispositivo e rimarrà in attesa della nostra scelta. Un esempio è quello riportato in figura.
3. Gestiamo il risultato dell’operazione ricavando l’account dall’intent dell’activity di Sing-In
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == Companion.RC_SIGN_IN) { val task = GoogleSignIn.getSignedInAccountFromIntent(data) try { val account = task.getResult(ApiException::class.java) updateInfoView(account, false) } catch (e: ApiException) { updateInfoView(null, true) } } }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_SIGN_IN) { Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); try { GoogleSignInAccount account = task.getResult(ApiException.class); updateInfoView(account, false); } catch (ApiException e) { updateInfoView(null, true); } } }
Logout E Disconnect
I metodi per eseguire il logout e il disconnect sono molto semplici. Non prevedono il lancio di nessuna activity ma semplicemente la chiamata al relativo metodo ( signOut
e revokeAccess
) dal client e l’attesa dell’evento di completamento. Non saranno inoltre necessari button specifici dell’SDK come nel caso del login ma utilizzeremo Button
standard.
<Button android:id="@+id/signOutButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Sign out" /> <Button android:id="@+id/disconnectButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Disconnect" />
@Click protected fun signOutButtonClicked() { googleSignInClient.signOut().addOnCompleteListener { updateInfoView(null, false) } } @Click protected fun disconnectButtonClicked() { googleSignInClient.revokeAccess().addOnCompleteListener { updateInfoView(null, false) } }
@Click protected void signOutButtonClicked() { googleSignInClient.signOut().addOnCompleteListener(task -> { updateInfoView(null, false); }); } @Click protected void disconnectButtonClicked() { googleSignInClient.revokeAccess().addOnCompleteListener(task -> { updateInfoView(null, false); }); }
Check login status
Per verificare in qualsiasi momento lo stato di login dell’utente sarà semplicemente necessario utilizzare il metodo getLastSignedInAccount
della classe GoogleSignIn
. Se l’account restituito è diverso da null
significa che l’utente è correttamente loggato altrimenti occorrerà riproporre la procedura di login finchè non sarà ultimata con successo.
val account = GoogleSignIn.getLastSignedInAccount(this); if(account != null) { // Utente già loggato } else { // Utente non loggato, avviare la procedura di login }
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); if(account != null) { // Utente già loggato } else { // Utente non loggato, avviare la procedura di login }
Autenticazione con backend
Un piccolo paragrafo va dedicato a chi vuole comunicare con un backend per l’autenticazione dell’utente. In questo caso dovremo farci restituire dal processo di Sing-In un token che comunicheremo al backend il quale si prenderà in carico la verifica dello stesso. Per fare questo dovremo innanzitutto recarci nella Google API Console e analogalmente a quanto spiegato precedentemente creiamo una chiave seguendo questi passaggi:
- Crea credenziali e selezioniamo ID client OAuth
- Tipo di applicazione: Applicazione web
- Nome: a scelta, esempio “Web OAuth”
- Crea
- Copiamo l’ID client che ci viene proposto (sarà comunque possibile visualizzarlo in seguito sul dettaglio della chiave)
A questo punto per ottenere il token dalla nostra applicazione andiamo ad operare le seguenti modifiche
- Creiamo un file nella directory values chiamato ad esempio strings_google_auth.xml e aggiungiamo un valore stringa che contiene l’ID client ricavato al precedente punto 5
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="google_client_id" translatable="false">ID cliente ottenuto</string> </resources>
- Modifichiamo la creazione del client facendo in modo di richiedere anche il token
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(resources.getString(R.string.google_client_id)) .requestEmail().build() googleSignInClient = GoogleSignIn.getClient(this, options)
GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getResources().getString(R.string.google_client_id)) .requestEmail() .build(); googleSignInClient = GoogleSignIn.getClient(this, options);
In questo modo quando l’utente avrà completato con successo il login, nell’oggetto account restituto la proprietà idToken verrà avvalorata con quello generato da Google.
Nota: il primo passo può essere evitato inserendo direttamente il valore nella chiave durante la creazione del client ma trovo la cosa poco elegante preferendo invece la scelta di avere i valori su file di configurazione .
Conclusioni
Come possiamo notare il processo di Sign-In risulta essere molto semplice, implica alcuni passaggi di configurazione che vanno seguiti attentamente ma per quanto riguarda il codice il tutto è molto lineare ed essenziale.
Indubbiamente per i motivi spiegati a inizio articolo, realizzare un’app con login attraverso piattaforme come Google è molto importante per uno sviluppatore quanto più apprezzata dall’utente finale quindi investire del tempo per la presenza di questa funzionalità è sicuramente ben speso.
Screenshots
Ecco alcuni screenshots dei passi descritti nell’articolo catturati dall’applicazione di esempio.
Riferimenti
Potere trovare tutti punti analizzati nell’app di esempio da me realizzata sul mio account di GitHub.
L’applicazione di esempio utilizza Android Annotations, per approfondire consultare l’articolo Android annotations: Meno codice, più leggibilità
Documentazione su Google Developers.