3

I need to make a PHP script that creates a sigle event on Google Calendar. I had no problems setting up client id, client secret, dev key and creating a new event.

My only problem is with OAuth2, in particular I need to make a permanent connection and I do not want to do the authentication everytime I run the script.

Actually, with this script I'm able to get a token and a refresh token, but every hour my token expires and I don't know how to refresh it. How can I edit this code to do that? Can I save both the token and the refresh token somewhere and always use the same data?

I obtain an uncaught exception 'Google_AuthException' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant"

I have already read some other posts about this topic here in stackoverflow but I still haven't found a solution... :\

<?php

 require_once 'src/Google_Client.php';
 require_once 'src/contrib/Google_CalendarService.php';
 session_start();

 $client = new Google_Client();
 $client->setApplicationName("Calendar App");
 $client->setClientId('xxxx');
 $client->setClientSecret('yyy');
 $client->setRedirectUri('http://www.zzzzzz');  
 $client->setDeveloperKey('kkk');
 $client->setAccessType('offline');
 $cal = new Google_CalendarService($client);    

if (isset($_GET['logout'])) {
  unset($_SESSION['token']);
}

if (isset($_GET['code'])) {
  $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); 
}

if (isset($_SESSION['token'])) {
    //echo $_SESSION['token'];
  //$client->setAccessToken($_SESSION['token']);
    $authObj = json_decode($_SESSION['token']);
    $accessToken = $authObj->access_token;
    $refreshToken = $authObj->refresh_token;
    $tokenType = $authObj->token_type;
    $expiresIn = $authObj->expires_in;
    echo 'access_token = ' . $accessToken;
    echo '<br />';
    echo 'refresh_token = ' . $refreshToken;
    echo '<br />';
    echo 'token_type = ' . $tokenType;
    echo '<br />';
    echo 'expires_in = ' . $expiresIn;
}

if(!empty($cookie)){
    $client->refreshToken($this->Cookie->read('token'));
}

if ($client->getAccessToken()) {
    $calList = $cal->calendarList->listCalendarList();
    $_SESSION['token'] = $client->getAccessToken();
} else {
  $authUrl = $client->createAuthUrl();
  print "<a class='login' href='$authUrl'>Connect Me!</a>";
}


// Creation of a single event
$event = new Google_Event();
$event->setSummary($event_name);            
$event->setLocation('');                    
....

?>

Thanks a lot for your support!

Roberto Milani
  • 700
  • 2
  • 17
  • 33

3 Answers3

5

This page https://developers.google.com/accounts/docs/OAuth2WebServer#offline explains how the refresh token works, and how to use it to get a fresh access token using raw http.

From this question How to refresh token with Google API client? here is the php equivalent

here is the snippet to set token, before that make sure the access type should be set to offline

if (isset($_GET['code'])) {
  $client->authenticate();
  $_SESSION['access_token'] = $client->getAccessToken();
}
To refresh token

$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);
this will refresh your token, you have to update it in session for that you can do

 $_SESSION['access_token']= $client->getAccessToken()

DEBUGGING Follow these three steps to debug any oauth application

  1. Make sure you have read https://developers.google.com/accounts/docs/OAuth2 and also the appropriate sub-page (webapp, javascript, etc) depending on which flavour of oauth you are using. You won't get very far debugging your app if you don't understand what it's doing.

  2. Use the Oauth Playground at https://developers.google.com/oauthplayground/ to walk through the Oauth steps and ultimately make a Google API call. This will confirm your understanding and show you what the http calls and responses look like

  3. Use tracing/logging/proxy etc to trace the actual http traffic from your app. Compare this with what you observed in step 2. This should show you where the problem lies.

Community
  • 1
  • 1
pinoyyid
  • 19,003
  • 12
  • 50
  • 100
  • Thanks for your answer but I'm still stuck on the problem. Now I got an 'Error refreshing the OAuth2 token, error" invalid_request" } I've edited the initial code this way: if (isset($_GET['code'])) { $client->authenticate(); $_SESSION['access_token'] = $client->getAccessToken(); header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); $google_token= json_decode($_SESSION['access_token']); $client->refreshToken($google_token->refresh_token); $_SESSION['access_token']= $client->getAccessToken(); } – Roberto Milani Nov 12 '13 at 14:30
  • and before all I've defined an hardcoded JSON with a token and its refresh token this way. $arr = array('access_token' => 'yz...', 'refresh_token' => 'xyz', 'token_type' => 'Bearer', 'expires_in' => 3600, 'created' => ...); $_SESSION['token'] = json_encode($arr); I dont understand when I have to refresh the token. Thanks in advance – Roberto Milani Nov 12 '13 at 14:30
  • I'm not going to look at your code (I don't know php). I've updated my answer with some tips on how to debug this kind of problem – pinoyyid Nov 12 '13 at 15:29
  • @Roberto: Did you ever find a fix for the "Error refreshing the OAuth2 token"? I am having the same issue. Thanks! – jftuga May 29 '14 at 15:43
2

I got this error before because I was trying to authenticate twice.

Since you have this line:

if (isset($_GET['code']))

It will try to authenticate when the code is in the query string regardless of whether you're already authenticated. Try checking whether the SESSION token is present before trying to (re)authenticate.

thayne
  • 186
  • 3
  • 11
0

Try removing setDeveloperKey(), this was causing some issues for me and it seems unneeded.

stealthysnacks
  • 881
  • 1
  • 9
  • 16