Oauth2 and google apis library for php

OAuth2 and Google APIs Library for PHP


This page is a follow up on our "Google Calendar on your Yocto-MaxiDisplay" post that explains show to display events from a Google calendar on a Yocto-MaxiDisplay. The aim of this page is to detail how to use the Google API from an HTTP callback which is called by a YoctoHub or a VirtualHub.

OAuth 2.0


To be able to use the Google API, we must authorize the PHP script to use the user data with the help of the OAuth 2.0 protocol. The OAuth 2.0 protocol allows a client site (our PHP script) to access the private data of a provider site (Google) without having the user needing to provide his/her password to the client site (our PHP script). Concretely, each web application using a Google service must pass as parameter its own "access token" for all requests to Google. This enables the user (or Google) to revoke the access token of one application without affecting other applications using the same service.

To obtain this access token, we must redirect the user on a page hosted by Google so that the user can log on (to the Google site, not to our own) and authorize our application to access the desired service (Google Calendar in our example). If the user authorizes our application to use the calendar, Google redirects the user to our web site passing as parameter an "authorization code" (valid only once) enabling the application to retrieve an "access token".

When you have an "access token", we must save it to avoid having to ask the user for the authorization again.

The  OAuth 2.0 authorization sequence
The OAuth 2.0 authorization sequence



To sum up, there are four steps to authorize a script to access Google services:

  1. The first time users connect themselves, they must be redirected to the Google site to authorize our script to connect itself to their calendar.
  2. When the users have authorized our script to connect itself to their calendar, Google redirects the users to our script with an "authorization code".
  3. The script detects the "authorization code" and sends a request to Google to exchange this code for an "access token" and a "refresh token".
  4. We save both in the database.


To make things more complex, the acces tokens expire and it is necessary to renegotiate a new acces token with a refresh token, which is provided only during the first token exchange.

When the access token expires, you must request a new one with the refresh token.
When the access token expires, you must request a new one with the refresh token.



When we have these two tokens, we can make as many requests to Google as we want, as long as all the requests come from the same server and as long as the user does not revoke our application.

Storing tokens


Before calling the Google API functions, we must be able to store the tokens between each execution. In its examples, Google uses session variables. This solution works well if you use a web browser which correctly manages cookies. But the YoctoHub doesn't support this option. We must therefore save the tokens in a file or in a database. We must therefore implement three functions (clearTokenInDb, updateTokenInDb, and getTokenFromDb).

The PHP script


The first step is to instantiate a Google_Client object with the parameters that we find in the "Developers Console". It is very important to remember to call setAccessType('offline'). Without this, Google won't provide the "refresh token" during authorization and we would have to ask the user to provide the authorization again when the access token expires.

  $client = new Google_Client();
  $client->setApplicationName("My Application");
  $client->setAccessType('offline');
  $client->setClientId('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  $client->setClientSecret('XXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  $client->setRedirectUri('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
  $client->addScope("https://www.googleapis.com/auth/calendar.readonly");



The first thing to do is to check if we have a code given as argument on the URL. If we do, the user has authorized our script with Google and he/she has been redirected on our script. The $_GET['code'] parameter contains the authorisation code returned by Google. With the authenticate method, we exchange this code against an access token and a refresh token. We must imperatively save these two tokens. Otherwise, we won't be able to access the Google API during the next execution. When the tokens are saved, we redirect the user again to our script to "clean" the URL of the "code" parameter.

  if (isset($_GET['code'])) {
    $client->authenticate($_GET['code']);
    $access_token = $client->getAccessToken();
    $tokens_decoded = json_decode($access_token);
    $refreshToken = $tokens_decoded->refresh_token;
    updateTokenInDb(..., $access_token, $refreshToken);
    $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
    header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
  }



If there are no access token in the database, it means that the user hasn't yet authorized our script. In this case, we call the createAuthUrl() method returning a URL enabling the user to authorize our script.

  $access_token = getTokenFromDb(...);
  if(!$access_token) {
    /**
    * HERE YOU HAVE NO SAVED TOKEN SO YOU
    * NEED TO REDIRECT THE USER ON $authUrl
    */

    $authUrl = $client->createAuthUrl();
    print_link($authUrl);
    die();
  }



On the other hand, if we have in the database an access token, we must assign it to the Google_Client object with the setAccessToken() method. We must also check that the access token is still valid. If it has expired, we must use the refreshToken() to renegotiate a new access token. This method takes as arguments the refresh token that we have saved during the first token exchange. We can then use the Google library to access all the services that the user has authorized.


  $client->setAccessToken($access_token['access_token']);
  if ($client->isAccessTokenExpired()) {
    $client->refreshToken($access_token['refresh_token']);
  }
  /**
  * HERE YOU CAN USE THE GOOGLE API
  * AND OUTPUT THE DATA
  */

  ...



At the end, we must remember to update the database with valid tokens (those that the library just used).

  $access_token = $client->getAccessToken();
  $tokens_decoded = json_decode($access_token);
  $refreshToken = $tokens_decoded->refresh_token;
  updateTokenInDb($access_token, $refreshToken);


Yoctopuce, get your stuff connected.