How to update token with Google API Client?

I played with the Google Analytics API (V3) and ran into som errors. Firstly, everything is configured correctly and works with my test account. But when I want to capture data from a different profile identifier (the same Google Accont / GA account), I get an error 403. It is strange that data from some GA accounts will return data, while others generate this error.

I revoked the token and passed the authentication again, and now it seems that I can capture data from all my accounts. Is the problem solved? Not. As the passkey expires, I will again be faced with the same issue.

If I understood everything correctly, I could use resfreshToken to get a new authentication for Tooken.

The problem is that I run:

$client->refreshToken(refresh_token_key) 

The following error is returned:

 Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }' 

Ive checked the code for the refreshToken method and sent the request back to the apiOAuth2.php file. All parameters are sent correctly. The type grant_type is hardcoded to 'refresh_token inside the method, so it's hard for me to understand what is wrong. An array of parameters is as follows:

 Array ( [client_id] => *******-uqgau8uo1l96bd09eurdub26c9ftr2io.apps.googleusercontent.com [client_secret] => ******** [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY [grant_type] => refresh_token ) 

The procedure is as follows.

 $client = new apiClient(); $client->setClientId($config['oauth2_client_id']); $client->setClientSecret($config['oauth2_client_secret']); $client->setRedirectUri($config['oauth2_redirect_uri']); $client->setScopes('https://www.googleapis.com/auth/analytics.readonly'); $client->setState('offline'); $client->setAccessToken($config['token']); // The access JSON object. $client->refreshToken($config['refreshToken']); // Will return error here 

Is this a mistake, or have I completely understood nothing?

+83
php google-api access-token google-analytics-api
Feb 11 '12 at 15:07
source share
17 answers

So, I finally figured out how to do this. The basic idea is that you have a token that you get on the first authentication request. This first token has an update token. The first original token expires in an hour. After an hour, you need to use the update token from the first token to get a new useful token. You use $client->refreshToken($refreshToken) to get a new token. I will call this "pace token." You also need to save this tempo token, because it expires in an hour, and also notes that it does not have the update token associated with it. To get the new temp token, you need to use the method you used earlier and use the first refreshtoken token. I have attached the code below, which is ugly, but im new in this ...

 //pull token from database $tokenquery="SELECT * FROM token WHERE type='original'"; $tokenresult = mysqli_query($cxn,$tokenquery); if($tokenresult!=0) { $tokenrow=mysqli_fetch_array($tokenresult); extract($tokenrow); } $time_created = json_decode($token)->created; $t=time(); $timediff=$t-$time_created; echo $timediff."<br>"; $refreshToken= json_decode($token)->refresh_token; //start google client note: $client = new Google_Client(); $client->setApplicationName(''); $client->setScopes(array()); $client->setClientId(''); $client->setClientSecret(''); $client->setRedirectUri(''); $client->setAccessType('offline'); $client->setDeveloperKey(''); //resets token if expired if(($timediff>3600)&&($token!='')) { echo $refreshToken."</br>"; $refreshquery="SELECT * FROM token WHERE type='refresh'"; $refreshresult = mysqli_query($cxn,$refreshquery); //if a refresh token is in there... if($refreshresult!=0) { $refreshrow=mysqli_fetch_array($refreshresult); extract($refreshrow); $refresh_created = json_decode($token)->created; $refreshtimediff=$t-$refresh_created; echo "Refresh Time Diff: ".$refreshtimediff."</br>"; //if refresh token is expired if($refreshtimediff>3600) { $client->refreshToken($refreshToken); $newtoken=$client->getAccessToken(); echo $newtoken."</br>"; $tokenupdate="UPDATE token SET token='$newtoken' WHERE type='refresh'"; mysqli_query($cxn,$tokenupdate); $token=$newtoken; echo "refreshed again"; } //if the refresh token hasn't expired, set token as the refresh token else { $client->setAccessToken($token); echo "use refreshed token but not time yet"; } } //if a refresh token isn't in there... else { $client->refreshToken($refreshToken); $newtoken=$client->getAccessToken(); echo $newtoken."</br>"; $tokenupdate="INSERT INTO token (type,token) VALUES ('refresh','$newtoken')"; mysqli_query($cxn,$tokenupdate); $token=$newtoken; echo "refreshed for first time"; } } //if token is still good. if(($timediff<3600)&&($token!='')) { $client->setAccessToken($token); } $service = new Google_DfareportingService($client); 
+72
Mar 13 '13 at 18:02
source share

The problem is the update token:

 [refresh_token] => 1\/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY 

When a line with '/' gets json encoded , it is escaped with '\' , so you need to delete it.

The update current in your case should be:

 1/lov250YQTMCC9LRQbE6yMv-FiX_Offo79UXimV8kvwY 

What I assume you did is that you printed the json string that google sent back and copied and pasted the token into your code, because if you are json_decode , it will correctly delete the '\' for you!

+38
Jan 19 '13 at 22:20
source share

The type of access must be set to offline . state is a variable that you set for your own use, not for using the API.

Make sure you have the latest client library and add:

 $client->setAccessType('offline'); 

See Generating URLs for an explanation of the parameters.

+17
Feb 11 '12 at 22:00
source share

here is a snippet for setting a token before making sure that the access type must be set to offline

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

Update Token

 $google_token= json_decode($_SESSION['access_token']); $client->refreshToken($google_token->refresh_token); 

this will update your token, you need to update it in the session so you can do

  $_SESSION['access_token']= $client->getAccessToken() 
+17
Feb 26 '13 at 5:30
source share

@ Uri-weg's answer worked for me, but since I did not find his explanation very clear, let me rephrase it a bit.

During the first sequence of access rights, in the callback, when you get to the point where you get the authentication code, you must also save the access token and the update token .

The reason is because the Google API sends you an access token with an update token only when you request access permission. The following access tokens will be sent without any update tokens (unless you use the approval_prompt=force option).

The update token you received for the first time remains valid until the user revokes the permission to access.

In a simplified php, an example of a callback sequence would be:

 // init client // ... $authCode = $_GET['code']; $accessToken = $client->authenticate($authCode); // $accessToken needs to be serialized as json $this->saveAccessToken(json_encode($accessToken)); $this->saveRefreshToken($accessToken['refresh_token']); 

And later, in simplified php, the connection sequence will be like this:

 // init client // ... $accessToken = $this->loadAccessToken(); // setAccessToken() expects json $client->setAccessToken($accessToken); if ($client->isAccessTokenExpired()) { // reuse the same refresh token $client->refreshToken($this->loadRefreshToken()); // save the new access token (which comes without any refresh token) $this->saveAccessToken($client->getAccessToken()); } 
+13
Jul 19 '16 at 15:24
source share

Here is the code that I use in my project and it works fine:

 public function getClient(){ $client = new Google_Client(); $client->setApplicationName(APPNAME); // app name $client->setClientId(CLIENTID); // client id $client->setClientSecret(CLIENTSECRET); // client secret $client->setRedirectUri(REDIRECT_URI); // redirect uri $client->setApprovalPrompt('auto'); $client->setAccessType('offline'); // generates refresh token $token = $_COOKIE['ACCESSTOKEN']; // fetch from cookie // if token is present in cookie if($token){ // use the same token $client->setAccessToken($token); } // this line gets the new token if the cookie token was not present // otherwise, the same cookie token $token = $client->getAccessToken(); if($client->isAccessTokenExpired()){ // if token expired $refreshToken = json_decode($token)->refresh_token; // refresh the token $client->refreshToken($refreshToken); } return $client; } 
+7
Aug 03 '16 at 5:55 on
source share

There was the same problem; my script that worked yesterday, for some odd reason, not today. Without changes.

Apparently, this is due to the fact that my system clock was turned off for 2.5 (!!) seconds, synchronization with NTP fixed it.

See also: https://code.google.com/p/google-api-php-client/wiki/OAuth2#Solving_invalid_grant_errors

+6
Aug 23 2018-12-12T00:
source share

FYI: 3.0 The Google Analytics API will automatically update the access token if you have an update token when it expires, so your script never needs a refreshToken .

(See Sign function in auth/apiOAuth2.php )

+3
Sep 14 '12 at 7:01
source share

Sometimes updating the token is not generated using $client->setAccessType ("offline"); .

Try the following:

 $client->setAccessType ("offline"); $client->setApprovalPrompt ("force"); 
+3
Feb 14 '17 at 13:10
source share

I used the example using smartcodes with the current version of the Google APIs, but this one did not work. I think its API is too outdated.

So, I just wrote my own version based on one of the API examples ... It displays the access token, request token, token, identifier token, expiration time and creation time as strings

If your credentials and your customer’s key are correct, this code should work out of the box.

 <?php // Call set_include_path() as needed to point to your client library. require_once 'google-api-php-client/src/Google_Client.php'; require_once 'google-api-php-client/src/contrib/Google_Oauth2Service.php'; session_start(); $client = new Google_Client(); $client->setApplicationName("Get Token"); // Visit https://code.google.com/apis/console?api=plus to generate your // oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri. $oauth2 = new Google_Oauth2Service($client); if (isset($_GET['code'])) { $client->authenticate($_GET['code']); $_SESSION['token'] = $client->getAccessToken(); $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL)); return; } if (isset($_SESSION['token'])) { $client->setAccessToken($_SESSION['token']); } if (isset($_REQUEST['logout'])) { unset($_SESSION['token']); $client->revokeToken(); } ?> <!doctype html> <html> <head><meta charset="utf-8"></head> <body> <header><h1>Get Token</h1></header> <?php if ($client->getAccessToken()) { $_SESSION['token'] = $client->getAccessToken(); $token = json_decode($_SESSION['token']); echo "Access Token = " . $token->access_token . '<br/>'; echo "Refresh Token = " . $token->refresh_token . '<br/>'; echo "Token type = " . $token->token_type . '<br/>'; echo "Expires in = " . $token->expires_in . '<br/>'; echo "ID Token = " . $token->id_token . '<br/>'; echo "Created = " . $token->created . '<br/>'; echo "<a class='logout' href='?logout'>Logout</a>"; } else { $authUrl = $client->createAuthUrl(); print "<a class='login' href='$authUrl'>Connect Me!</a>"; } ?> </body> </html> 
+2
Nov 15 '13 at 3:33
source share

I have the same problem with google / google-api-php-client v2.0.0-RC7 and after searching for 1 hour I solved this problem using json_encode for example:

  if ($client->isAccessTokenExpired()) { $newToken = json_decode(json_encode($client->getAccessToken())); $client->refreshToken($newToken->refresh_token); file_put_contents(storage_path('app/client_id.txt'), json_encode($client->getAccessToken())); } 
+1
May 08 '16 at 10:10
source share

This works very well, maybe it can help anyone:

index.php

 session_start(); require_once __DIR__.'/client.php'; if(!isset($obj->error) && isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in)) { ?> <!DOCTYPE html> <html> <head> <title>Google API Token Test</title> <meta charset='utf-8' /> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script> search('Music Mix 2010'); function search(q) { $.ajax({ type: 'GET', url: 'action.php?q='+q, success: function(data) { if(data == 'refresh') location.reload(); else $('#response').html(JSON.stringify(JSON.parse(data))); } }); } </script> </head> <body> <div id="response"></div> </body> </html> <?php } else header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/oauth2callback.php', FILTER_SANITIZE_URL)); ?> 

oauth2callback.php

 require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google_Client(); $client->setAuthConfigFile('auth.json'); $client->setAccessType('offline'); $client->setApprovalPrompt('force'); $client->setRedirectUri('https://'.filter_var($_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'], FILTER_SANITIZE_URL)); $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL); if(isset($_GET['code']) && $_GET['code']) { $client->authenticate(filter_var($_GET['code'], FILTER_SANITIZE_STRING)); $_SESSION['access_token'] = $client->getAccessToken(); $_SESSION['refresh_token'] = $_SESSION['access_token']['refresh_token']; setcookie('refresh_token', $_SESSION['refresh_token'], time()+60*60*24*180, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true); header('Location: '.filter_var('https://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']), FILTER_SANITIZE_URL)); exit(); } else header('Location: '.filter_var($client->createAuthUrl(), FILTER_SANITIZE_URL)); exit(); ?> 

client.php

 // https://developers.google.com/api-client-library/php/start/installation require_once __DIR__.'/vendor/autoload.php'; $client = new Google_Client(); $client->setAuthConfig('auth.json'); $client->setAccessType('offline'); $client->setApprovalPrompt('force'); $client->addScope(Google_Service_YouTube::YOUTUBE_FORCE_SSL); // Delete Cookie Token #setcookie('refresh_token', @$_SESSION['refresh_token'], time()-1, '/', filter_var($_SERVER['HTTP_HOST'], FILTER_SANITIZE_URL), true, true); // Delete Session Token #unset($_SESSION['refresh_token']); if(isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) { $client->refreshToken($_SESSION['refresh_token']); $_SESSION['access_token'] = $client->getAccessToken(); } elseif(isset($_COOKIE['refresh_token']) && $_COOKIE['refresh_token']) { $client->refreshToken($_COOKIE['refresh_token']); $_SESSION['access_token'] = $client->getAccessToken(); } $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.urlencode(@$_SESSION['access_token']['access_token']); $curl_handle = curl_init(); curl_setopt($curl_handle, CURLOPT_URL, $url); curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Google API Token Test'); $json = curl_exec($curl_handle); curl_close($curl_handle); $obj = json_decode($json); ?> 

action.php

 session_start(); require_once __DIR__.'/client.php'; if(isset($obj->error)) { echo 'refresh'; exit(); } elseif(isset($_SESSION['access_token']) && $_SESSION['access_token'] && isset($obj->expires_in) && isset($_GET['q']) && !empty($_GET['q'])) { $client->setAccessToken($_SESSION['access_token']); $service = new Google_Service_YouTube($client); $response = $service->search->listSearch('snippet', array('q' => filter_input(INPUT_GET, 'q', FILTER_SANITIZE_SPECIAL_CHARS), 'maxResults' => '1', 'type' => 'video')); echo json_encode($response['modelData']); exit(); } ?> 
+1
Aug 05 '17 at 15:56 on
source share

I am using google-api-php-client v2.2.2. I get a new token with fetchAccessTokenWithRefreshToken(); if the function call without parameters, it returns the updated access token and the updated token is not lost.

 if ($client->getAccessToken() && $client->isAccessTokenExpired()) { $new_token=$client->fetchAccessTokenWithRefreshToken(); $token_data = $client->verifyIdToken(); } 
+1
Apr 15 '19 at 16:23
source share

According to google authentication: OAuth2 continues to return 'invalid_grant'

"You must reuse the access token that you will receive after the first successful authentication. You will receive an invalid_grant error if your previous token has not expired. Download it somewhere so you can reuse it."

hope this helps

0
Aug 29 2018-12-12T00:
source share

Google has made some changes since this question was first published.

Here is my current working example.

  public function update_token($token){ try { $client = new Google_Client(); $client->setAccessType("offline"); $client->setAuthConfig(APPPATH . 'vendor' . DIRECTORY_SEPARATOR . 'google' . DIRECTORY_SEPARATOR . 'client_secrets.json'); $client->setIncludeGrantedScopes(true); $client->addScope(Google_Service_Calendar::CALENDAR); $client->setAccessToken($token); if ($client->isAccessTokenExpired()) { $refresh_token = $client->getRefreshToken(); if(!empty($refresh_token)){ $client->fetchAccessTokenWithRefreshToken($refresh_token); $token = $client->getAccessToken(); $token['refresh_token'] = json_decode($refresh_token); $token = json_encode($token); } } return $token; } catch (Exception $e) { $error = json_decode($e->getMessage()); if(isset($error->error->message)){ log_message('error', $error->error->message); } } } 
0
Jul 18 '18 at 14:14
source share

During the initial authorization request, you must save the access token to the file or database as a json string and set the access type to offline mode $client->setAccessType("offline")

Then, during subsequent API requests, extract the access token from your file or database and pass it to the client:

 $accessToken = json_decode($row['token'], true); $client->setAccessToken($accessToken); 

Now you need to check if the token has expired:

 if ($client->isAccessTokenExpired()) { // access token has expired, use the refresh token to obtain a new one $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); // save the new token to file or db // ...json_encode($client->getAccessToken()) 

The fetchAccessTokenWithRefreshToken() function will do all the work for you and provide a new access token, save it back to a file or database.

0
Apr 26 '19 at 18:42
source share

use the following code snippet to get update token

  <?php require_once 'src/apiClient.php'; require_once 'src/contrib/apiTasksService.php'; $client = new apiClient(); $client->setAccessType('offline'); $tasksService = new apiTasksService($client); $auth = $client->authenticate(); $token = $client->getAccessToken(); // the refresh token $refresh_token = $token['refresh_token']; ?> 
-one
Jul 03 2018-12-17T00:
source share



All Articles