1

I am trying to use the refresh token to exchange the access token after the access token is expired. However, I keep facing problem like "invalid_grant" while doing so.

I guess there is some problem while I am trying to exchange refresh_token for new access_token. My code are shown below:

<?php require_once 'google-api-php-client/src/Google_Client.php'; require_once 'google-api-php-client/src/contrib/Google_PlusService.php'; require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php'; session_start(); $client = new Google_Client(); $client->setApplicationName("My app"); $client->setApprovalPrompt (auto); //prompt consent screen only for first time //*********** Replace with Your API Credentials ************** $client->setClientId('xxx.apps.googleusercontent.com'); $client->setClientSecret('xxx'); $client->setRedirectUri('http://example.com/oauth2callback'); $client->setDeveloperKey('xxx'); //************************************************************ $client->setScopes(array('https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.email')); $client->refreshToken(file_get_contents('refreshtoken.conf')); //retrieve refresh_token from file $client->setAccessToken("refresh_token"); // I guess something is wrong here. I am trying to pass the refresh token to get a new access token but not sure if this is correct $client->authenticate(); //after that authenticate user $plus = new Google_PlusService($client); $oauth2 = new Google_Oauth2Service($client); // Call the OAuth2 class for get email address if (isset($_REQUEST['logout'])) { unset($_SESSION['access_token']); } if (isset($_GET['code'])) { $client->authenticate(); $_SESSION['access_token'] = $client->getAccessToken(); header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); } if (isset($_SESSION['access_token'])) { $client->setAccessToken($_SESSION['access_token']); } if ($client->getAccessToken()) { $user = $oauth2->userinfo->get(); $me = $plus->people->get('me'); $email = filter_var($user['email'], FILTER_SANITIZE_EMAIL); // get the USER EMAIL ADDRESS using OAuth2 $optParams = array('maxResults' => 100); $activities = $plus->activities->listActivities('me', 'public', $optParams); $jsonarray = json_decode($client->getAccessToken()); $arrGoogleAuth['access_token']=$jsonarray->access_token; $arrGoogleAuth['refresh_token']=$jsonarray->refresh_token; //filewrite $myFile = "refreshtoken.conf"; $fh = fopen($myFile, 'w') or die("can't open file"); //write the json into refresh.conf fwrite($fh, $client->getAccessToken()); fclose($fh); $_SESSION['access_token'] = $client->getAccessToken(); } else { $authUrl = $client->createAuthUrl(); } ?> 

2 Answers 2

1

Without being an expert on the PHP client library, looking at the code for it, I believe the following subset/slight change of your code should be sufficient (assuming you've previously successfully requested offline access, got back a refresh token and persisted the output of $client->getAccessToken()) (should be a JSON object):

require_once 'google-api-php-client/src/Google_Client.php'; require_once 'google-api-php-client/src/contrib/Google_PlusService.php'; require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php'; session_start(); $client = new Google_Client(); $client->setApplicationName("My app"); $client->setClientId('xxx.apps.googleusercontent.com'); $client->setClientSecret('xxx'); $client->setRedirectUri('http://example.com/oauth2callback'); $client->setDeveloperKey('xxx'); $client->setScopes(array('https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.email')); $client->setAccessToken(file_get_contents('refreshtoken.conf')); $plus = new Google_PlusService($client); $oauth2 = new Google_Oauth2Service($client); 

Basically the output of $client->getAccessToken() includes an access token, refresh token (if granted), time to live info etc. Assuming you persist that JSON blob, then set it, you can go ahead and just use the Google_PlusService (and other Google APIs) - they will automatically check if the access token is expired and use the refresh token to get a new access token as needed.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi, aeijdenberg. By following your suggestion, the refresh token will be used to exchange the access token from Google server. I have another problem now, every user who login to my system will login by using my account since I kind of like hard-coded the refresh token of mine into the program. Is there any suggestion you can give so that every user will have their individual refresh token ? I think my idea of saving it in refreshtoken.conf is not the right approach.
Correct - you shouldn't be storing it in refreshtoken.conf - I'd assumed that was for testing. You will need to persist it in whatever database/storage system is appropriate for your application. If you don't need to actually have offline access (access when the user is not present) you could just request an access token and store that in the user session instead which may be simpler. I'm not a PHP expert so I can't give you best guidance on how to do that.
I actually don't need the offline access. I tried to store the access token in a session. Somehow, the access token will expire in one hour, then the user will not be able to access that already which they will need to clear the browse cache first in order to login again. Any suggestion ? Thanks again, man.
1
if ($client->getAccessToken()) { if($client->isAccessTokenExpired()) { $client->authenticate(); $NewAccessToken = json_decode($client->getAccessToken()); $client->refreshToken($NewAccessToken->refresh_token); } else { $user = $oauth2->userinfo->get(); $me = $plus->people->get('me'); $email = filter_var($user['email'], FILTER_SANITIZE_EMAIL); // get the USER EMAIL ADDRESS using OAuth2 $optParams = array('maxResults' => 100); $activities = $plus->activities->listActivities('me', 'public', $optParams); $_SESSION['access_token'] = $client->getAccessToken(); } } else { $authUrl = $client->createAuthUrl(); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.