Ciao ragazzi, in questo articolo voglio condividere con voi l’esperienza che ho fatto giocando con alcune Google API.
La particolarità di questo esempio è che interagiremo con il mondo (grande!) delle Google API con un linguaggio tipicamente “backend”, ovvero il C++.
Data la vastità dell’argomento che spazia decisamente tante cose, ho preferito dividere l’articolo in due parti.
In questa prima parte faremo un’introduzione all’argomento molto discorsiva ma anche pratica.
Vedremo prima qualche accenno teorico e poi proveremo a creare un progetto nella Google Developers Console.
Questo, ci consentirà, nella seconda parte dell’articolo, di poter utilizzare il nostro client C++ e di invocare qualche Google API.
Un client rest in c++
Prima di dedicarmi, hobbysticamente, all’implementazione di un client per le Google API; qualche mese fa, per lavoro, ho dovuto implementare un’applicazione backend che tra le varie funzionalità doveva essere client di un servizio REST.
L’applicazione, per una serie di motivi, doveva essere scritta in C++, pertanto, ho dovuto implementare un client REST che potesse facilmente integrarsi con quel linguaggio.
Quindi, mi sono messo a cercare un client HTTP C++ già pronto su GitHub.
Ho deciso di puntare su una libreria molto leggera, senza troppi fronzoli che aveva una licenza MIT per l’utilizzo in software commerciale.
Stiamo parliamo di restclient-cpp, ovvero un comodo wrapper di curl.
L’esempio che vedremo, utilizzerà lo stesso approccio.
OAuth2
Google e molti altri utilizzano OAuth2 come protocollo di autenticazione per le loro API REST pubbliche.
Questo protocollo sta diventando o è già diventato lo standard per l’autenticazione delle chiamate REST via HTTP.
Qualche cenno storico: OAuth2 è stato definito nel 2012 come la naturale evoluzione di OAuth, che aveva visto la luce solo due anni prima.
Ad oggi OAuth versione 1 è deprecato ed in disuso.
OAuth2 è un protocollo di autenticazione abbastanza complicato che nella fase iniziale prevede alcune fasi di interazione tra i vari attori coinvolti.
Cerchiamo innanzitutto di dire quello che OAuth2 cerca di risolvere.
Autenticarsi, oggi
Il processo di autenticazione oggi, si è notevolmente evoluto rispetto al passato, quando cioè molto spesso bastava possedere uno user ed una password.
Ai giorni nostri, tuttavia, i sistemi informatici sono cresciuti esponenzialmente sia in termini di complessità che di funzionalità.
Visto che ci interagiremo, prendiamo proprio l’esempio di Google.
Inizialmente, attorno al 2005, Google introdusse Gmail.
Con un solo servizio, ancora il modello utente e password poteva funzionare.
Col tempo però, Google e così molti altri, estesero i loro sistemi e cominciarono letteralmente ad inondarci di nuove funzionalità.
Google mise nel suo paniere: Maps, Drive, Documents, YouTube, Google+, Wave, etc etc.
Col moltiplicarsi delle funzionalità, ci si rese ben presto conto che il modello basato sull’autenticazione classica basata su di uno user ed una password non avrebbe potuto scalare.
PROBLEMATICHE NOTE
L’autenticazione mediante user e password, in un contesto in cui esistono un numero arbitrario di applicazioni che fanno capo ad un unico account espone il fianco a svariati problemi:
- Credenziali compromesse: se ci rubano la password l’hanno rubata per tutte le applicazioni.
- Eccesso di visibilità sull’account dell’utente: ogni applicazione può potenzialmente avere accesso a tutti i dati dell’utente in modo indiscriminato.
- Impossibilità di revoca per una sessione compromessa: se ci rubano il cellulare dobbiamo per forza cambiare la password del nostro account.
Da queste categorie principali si possono ovviamente derivare miriadi di altre problematiche. Per gli interessati ad approfondire è sufficiente effettuare qualche ricerca sul motore di ricerca preferito.
la soluzione
È possibile risolvere (o tentare di risolvere) le problematiche sopra elencate definendo uno standard di iterazioni tra le varie entità e vari attori che interagiscono con i nostri account.
Al giorno d’oggi l’account di un utente tende ad essere visto come un’entità a se stante. In passato questo non era così vero, infatti, un account era spesso intimamente legato con un’applicazione specifica.
Ancora oggi, un account contiene tutte le informazioni sensibili di un utente: le sue informazioni anagrafiche, i suoi contatti, le coordinate GPS delle posizioni registrate, i suoi files salvati sul cloud, le sue carte di credito, eccetera eccetera…
Col passare del tempo è sempre più difficile trovare un’unica applicazione in grado di accedere a tutto quello che in un account è stato salvato nel tempo dal legittimo proprietario.
Oggi si preferisce che le singole applicazioni, molto specializzate, chiedano il permesso all’utente di fornire un accesso parziale ad alcuni segmenti dell’account molto ben definiti.
Perchè, per esempio, fornire all’applicazione Maps l’accesso ai files dell’utente salvati su Drive?`
No, è giusto che Maps possa lavorare sul proprio ambito – scope – di API messe a disposizione.
Quindi, visto che oggi Google usa OAuth2 per le sue API, un’applicazione client dell’account di un utente dovrà completare i seguenti passi logici:
- Chiedere il permesso all’utente di accedere ad un qualche scope del proprio account.
- Ùna volta ricevuta l’approvazione esplicita dell’utente rispetto allo scope che sta richiedendo, il client riceve un codice di autorizzazione.
- Il codice di autorizzazione così ricevuto può essere utilizzato dal client per ottenere un token di accesso temporaneo.
- Il token di accesso può essere utilizzato per effettuare le chiamate alle API per le quali quel token è valido.
OAuth2 – Ruoli
Nel protocollo OAuth2 si distinguono quattro ruoli:
- Resource Owner (user, utente): entità che concede al client l’accesso alle risorse protette in un qualche scope.
- Resource Server (servizio): server in cui vengono salvati i dati protetti di un Resource Owner, è di fatto il server che espone l’API finale che siamo interessati ad invocare.
- Client (third-party application): applicazione desktop, web o mobile che chiede l’accesso ai dati protetti del Resource Owner.
- Server di autorizzazione: server che autentica il Resource Owner e rilascia un token di accesso temporaneo ad un ambito di applicazione (scope).
I servizi e le Google API
Google nel tempo ha rilasciato davvero tante API per i suoi servizi.
Con queste è possibile fare pressochè qualunque cosa con la moltitudine di servizi che il gigante del web ha messo in piedi nel corso della sua storia.
Con le vostre applicazioni potete scambiare dati con Drive, Gmail, Calendar, Blogger o anche chiedere dati analitici da YouTube.
Oltre a questi e a molti altri ci sono miriadi di servizi in cloud che sono disponibili per l’utilizzo.
Ogni API ha la sua generosa quota di utilizzo gratuito.
Ad ogni modo, la lista completa di API è disponibile qui.
Bene, bando alle ciancie, entriamo nel nostro account Google e cominciamo a smanacciare.
creiamo IL nostro progetto
Prima di tutto dobbiamo creare un progetto, la nostra applicazione, nella Google Developers Console.
Colleghiamoci al seguente indirizzo: https://console.developers.google.com/
Vedrete quindi la action bar in alto nella pagina:
Selezionando la lista di progetti si aprirà una finestra modale nella quale potrete creare il vostro progetto:
Possiamo dare al progetto il nome che preferiamo, io l’ho chiamato: “testOAuth2“.
aggiungiamo una google api
Bene, a questo punto, una volta creato il progetto, possiamo dare un’occhiata al menù laterale che contiene alcune voci. Selezioniamo: Dashboard se già non fosse selezionata.
Nella pagina principale, possiamo cliccare sopra: Alibita API e Servizi.
Si aprirà una pagina in cui potrete effettuare una ricerca; digitando “drive” la prima proposta che otterremo sarà relativa alle Google Drive API. Abilitiamole.
Prima di proseguire, facciamo un salto alla documentazione della API e diamo un’occhiata alla pagina relativa all’autenticazione degli utenti.
Come potete vedere, Per le sue API, Google fornisce una lista di scopes con i quali lo sviluppatore può decidere di operare a seconda delle sue necessità.
Segnamoci da qualche parte lo scope di Drive più safe possibile: ovvero lo scope per operare in read-only.
https://www.googleapis.com/auth/drive.apps.readonly
Questo scope ci servirà più avanti quando andremo a richiedere il codice di autorizzazione o authentication code.
Credenziali e Schermata consenso OAuth
Procediamo adesso con il setup per dotare la nostra applicazione delle credenziali OAuth2 necessarie a consentire l’accesso all’account dell’utente (limitato all’ambito applicativo, scope, delle API che si voglio usare).
Schermata consenso OAuth dell’applicazione
Questa pagina sarà quella che la vostra applicazione visualizzerà quando richiederà il vostro consenso per accedere ad una porzione (scope) dell’account dell’utente.
All’atto pratico, per gli scopi del nostro esempio, possiamo limitarci a riempire il campo: Nome applicazione; diamo lo stesso nome del progetto: “testOAuth2“.
Questo nome comparirà nella lista di applicazioni a cui è stato concesso il permesso ad accedere ad un account Google.
GENERIAMO LE CREDENZIALI DEll’applicazione
Attraverso la voce: Credenziali potremo attivare il menù di creazione delle credenziali, selezioniamo quindi: ID client OAuth.
Queste credenziali che andremo a creare, sono utilizzate dalla vostra applicazione per poter accedere all’account dell’utente mediante il protocollo OAuth2 .
Nota bene: queste credenziali di per sé *non* consentono l’accesso all’account di alcun utente Google.
Queste credenziali saranno utilizzate durante tutto il processo iniziale di negoziazione del token di autorizzazione di OAuth2.
Ovviamente, ogni utente della vostra applicazione dovrà istanziare il proprio token di autorizzazione per poter accedere al proprio account Google.
Semplicemente, queste credenziali ID client OAuth sono logicamente associate alla vostra applicazione (client).
Ok, dopo queste doverose precisazioni, proseguiamo e scegliamo la tipologia della nostra applicazione: scegliamo Applicazione desktop.
Proseguiamo scegliendo un nome simbolico per queste credenziali, io ho scelto: “cppOAuth2RestClient“.
Per finire, clicchiamo sul bottone crea.
Con la creazione dell’ID client OAuth otteniamo in cambio la coppia: clientID e clientSecret.
Il clientID e il clientSecret saranno elementi statici della vostra applicazione.
Una volta generati, come abbiamo appena fatto, rimarranno sempre quelli.
Potremo pensare, quindi, di includerli in qualche file di risorsa statico nella nostra applicazione, come ad esempio, un file di properties.
otteniamo l’authorization code
Con tutti questi ingredienti sul tavolo, siamo adesso in grado di richiedere a Google un primo codice di autorizzazione, ovvero: l’authorizazion code.
Che cosa è e a cosa serve questo codice?
Questo codice è la stringa che viene restituita alla vostra applicazione dopo che l’utente ha autorizzato la stessa ad operare su un particolare scope di una API.
Le applicazioni che vogliono accedere al vostro account mediante una API, internamente costruiscono una URI che tra i parametri contiene anche il clientID.
Viene poi effettuata una GET della URI così costruita e alla fine del processo, se tutto va bene, l’applicazione si ritrova in mano l’authorizazion code.
Nota prima di proseguire: Google mette a disposizione dei programmatori svariate tonnellate di documentazione su come effettuare tutto il processo di autenticazione.
Fortunatamente, grazie a questo tutorial non dovrete leggervelo 😉 .
LA url per ottenere l’authorization code
Useremo il browser per ottenere l’authorization code. Dovremo chiamare:
https://accounts.google.com/o/oauth2/v2/auth
con i seguenti parametri GET.
- client_id, useremo il valore ottenuto dallo step di creazione delle Credenziali.
- response_type, useremo la stringa: “code“.
- scope, sappiamo che le API possiedono svariati scope.
Scegliamo:https://www.googleapis.com/auth/drive.apps.readonly
. - redirect_uri, useremo:
http://localhost
- access_type, useremo la stringa: “refresh_token“.
La nostra URI apparirà fatta così:
https://accounts.google.com/o/oauth2/v2/auth?client_id=924398787249-30oarj7dvh4i8ghcbo5jltfk2npe5rsb.apps.googleusercontent.com&response_type=code&scope=https://www.googleapis.com/auth/drive.readonly&redirect_uri=http://localhost&access_type=offline
Copiamo e incolliamo la URI nel browser e battiamo invio.
Se il vostro browser riesce a trovare un cookie con una sessione autorizzata al vostro account, vi sarà risparmiato di inserire email e password e vi verrà mostrata direttamente la seguente pagina:
Spengiamo qualunque processo che stia girando sul nostro pc che sia in listening sull’interfaccia di loopback alla porta TCP 80 e clicchiamo su Consenti.
La URI rediretta sarà qualcosa del genere:
http://localhost/?code=4/2jHjw_-ZwtYjDbW1ynYWj23Lehb0WmN61EgrzqHr0_XPYSytj2jOGJmKl5iofRcsub_GkIA2GAoDoFEyigCzy8s&scope=https://www.googleapis.com/auth/drive.readonly
A questo punto possiamo estrarre l’authorizazion code della nostra applicazione ed associato al nostro account personale:
4/2jHjw_-ZwtYjDbW1ynYWj23Lehb0WmN61EgrzqHr0_XPYSytj2jOGJmKl5iofRcsub_GkIA2GAoDoFEyigCzy8s
Salviamo la stringa da qualche parte, ci servirà in seguito.
Molto bene. Se siamo arrivati fin qui senza intoppi abbiamo già fatto parecchio.
considerazioni finali
Alla fine di questa prima parte del nostro viaggio introduttivo alle Google API abbiamo fatto un po’ di cose, proviamo a riassumerle:
- Abbiamo creato un progetto chiamato “testOAuth2” nella Google Developers Console.
- Abbiamo abilitato le Google Drive API per questo progetto.
- Mediante l’apposita sezione, abbiamo definito la schermata di consenso OAuth per l’applicazione.
- Mediante l’apposita sezione, abbiamo creato le credenziali dell’applicazione di tipo ID client OAuth. Da questo step abbiamo ottenuto il clientID e il clientSecret.
- Con i dati che avevamo, abbiamo composto la URI per ottenere un primo codice di autorizzazione associato al nostro account Google che sia utilizzabile dalla nostra applicazione; ovvero l’authorization code.
C’è da dire ancora una cosa prima di salutarci e di darci appuntamento alla seconda parte di questo articolo.
Qualcuno potrebbe avere giustamente dei dubbi sul punto 5.
Per ottenere l’authorization code sembra che abbiamo fatto qualche magia manuale di troppo…
Non dovrebbe essere il client stesso ad occuparsi di negoziare l’authorization code?
Noi abbiamo fatto attraverso un browser… Ma non dovrebbe essere la nostra applicazione a mostrare all’utente la schermata di consenso?
La risposta può essere si se l’applicazione è un’app reale per cellulare o per desktop.
La nostra però, sarà un’applicazione backend, di esempio, scritta in C++.
Non è proprio banale fare in modo che un’applicazione del genere, che nemmeno possiede una GUI, possa visualizzare una pagina HTML con cui l’utente deve interagire.
Per applicazioni del genere, in primissima istanza, ha senso che siamo noi, manualmente, a negoziare l’authorization code via web browser.
Bene, sperando di essere stato sufficientemente chiaro nell’affrontare un argomento così vasto, vi do appuntamente alla seconda parte di questo articolo.
Utilizzeremo tutto quello che abbiamo prodotto in questa prima parte e vedremo il client C++ all’opera sulla Google API Drive.
Un saluto e a Presto!
https://italiancoders.it/google-api-in-salsa-c-prima-parte/