In questo post spiegheremo come usare Google Sign-In con il back-end. Grazie a questa funzione, gli utenti che eseguono l’accesso sul proprio dispositivo possono ottenere un’autenticazione sicura per accedere ai rispettivi dati sui server di back-end degli sviluppatori.
Uso delle credenziali sui server degli sviluppatori
Innanzitutto osserviamo cosa succede se un utente esegue l’accesso a un’app ma necessita anche dell’autenticazione per accedere al server di back-end dello sviluppatore. Prendiamo in considerazione questo scenario: lo sviluppatore ha creato un’app che offre cibo a domicilio agli utenti. Gli utenti eseguono l’accesso all’app e questa ne recupera i dati identificativi. Lo sviluppatore archivia l’indirizzo e le preferenze dell’ordine dell’utente in un database sul proprio server.
A meno che gli endpoint del server non siano protetti tramite determinati meccanismi di autenticazione, eventuali aggressori possono leggere e scrivere i dati sul database degli utenti semplicemente indovinando i loro indirizzi email.
|
Figura 1. Un estraneo può effettuare lo spoofing del server con una falsa email |
Non si tratta solo di una brutta esperienza per l’utente, esiste il rischio che i dati del cliente possano essere sottratti o usati in modo improprio. Questo può essere evitato ottenendo un token da Google quando l’utente accede all’app e trasferendo successivamente questo token al server dello sviluppatore. Il server convalida dunque questo token effettivamente emesso da Google per l’utente desiderato e previsto per l’app (in base all’impostazione dei destinatari, vedi di seguito). A questo punto il server è in grado di capire che la chiamata viene effettivamente effettuata dall’utente e non da un malintenzionato e può rispondere con i dettagli necessari.
|
Figura 2. I falsi token di terzi verranno rifiutati |
Diamo uno sguardo ai passaggi di questa procedura:
Fase 1. L’app Android ottiene un token ID (*) dopo aver effettuato l’accesso con Google. È disponibile un ottimo esempio che dimostra la procedura
qui. A tal fine, il metodo requestIdToken viene chiamato quando si crea l’oggetto GoogleSignInOptions.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_id))
.requestEmail()
.build();
Ciò richiede di ottenere un ID client per il server dello sviluppatore. Le informazioni su come ottenere questo ID sono disponibili
qui (vedi Fase 4).
Non appena l’app Android dispone del token, lo può POSTARE
tramite HTTPS sul server, che tenterà quindi di convalidarlo.
(*) Un token ID è JSON Web Token, in conformità con lo standard
RFC7519. Si tratta di un metodo aperto, standard del settore, per l’espressione di richieste in modo sicuro tra due parti.
Fase 2. Il server riceve il token dal client Android. Deve quindi convalidare il token con i metodi indicati in particolare nelle librerie
Google API Client, verificando che sia emesso da Google e che il destinatario previsto sia il server dello sviluppatore.
Il server può utilizzare la classe
GoogleIdTokenVerifier per verificare il token ed estrarre quindi i dati identificativi necessari. Il campo “sub” (disponibile tramite il metodo getSubject()) fornisce un identificatore della stringa stabile che deve essere usato per identificare gli utenti anche se i rispettivi indirizzi email cambiano e per inserirli nel database. Sono disponibili altri campi di token ID, tra cui nome, indirizzo email e URL foto. Questo è un
esempio di un servlet testato su Google App Engine che può verificare i token utilizzando una libreria fornita. Tali librerie consentono di verificare il token localmente senza una chiamata di rete.
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// Here is where the audience is set -- checking that it really is your server
// based on your Server’s Client ID
.setAudience(Arrays.asList(ENTER_YOUR_SERVER_CLIENT_ID_HERE))
// Here is where we verify that Google issued the token
.setIssuer("https://accounts.google.com").build();
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
Payload payload = idToken.getPayload();
String userId = payload.getSubject();
// You can also access the following properties of the payload in order
// for other attributes of the user. Note that these fields are only
// available if the user has granted the 'profile' and 'email' OAuth
// scopes when requested. Even when requested, some fields may be null.
// String email = payload.getEmail();
// boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
// String name = (String) payload.get("name");
// String pictureUrl = (String) payload.get("picture");
// String locale = (String) payload.get("locale");
// String familyName = (String) payload.get("family_name");
// String givenName = (String) payload.get("given_name");