3

I have a Prediction app that's based on Google-api-php client version 1.0.0 latest. it's perfectly working in the localhost environment. but when I deploy same exact app into the hosting server environment it's gave me following issue.

THIS IS THE ERROR I GOT FROM HOSTING ENVIRONMENT

Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'' in /home/predict/public_html/predict/Google/Auth/OAuth2.php:335 Stack trace: #0 /home/predict/public_html/predict/Google/Auth/OAuth2.php(294): Google_Auth_OAuth2->refreshTokenRequest(Array) #1 /home/predict/public_html/predict/index.php(40): Google_Auth_OAuth2->refreshTokenWithAssertion(Object(Google_Auth_AssertionCredentials)) #2 {main} thrown in /home/predict/public_html/predict/Google/Auth/OAuth2.php on line 335

*CURL and JSON extensions are working properly under Hosting environment.

THIS IS MY WHOLE SOURCE CODE

<?php
session_start();

set_include_path("Google" . PATH_SEPARATOR . get_include_path());
require_once 'Client.php';
require_once 'Service/Prediction.php';

$client_id              = 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns.apps.googleusercontent.com';    
$service_account_name   = 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns@developer.gserviceaccount.com';  
$key_file_location      = 'APPKEY-d333c55a111a.p12';

if ($client_id == 'XXXXXXXXXX-uin70k09g5g6f05vqvdj9ch541c4spns.googleusercontent.com'
    || !strlen($service_account_name)
    || !strlen($key_file_location)) {  
}

$client = new Google_Client();

$client->setApplicationName("Predition App");
$service = new Google_Service_Prediction($client);

if (isset($_SESSION['service_token'])) {
  $client->setAccessToken($_SESSION['service_token']);
}

$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
    $service_account_name,`enter code here`
    array('https://www.googleapis.com/auth/prediction'),
    $key
);

$client->setAssertionCredentials($cred);

if($client->getAuth()->isAccessTokenExpired()) {    
  $client->getAuth()->refreshTokenWithAssertion($cred); 
}

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

// Prediction logic:
$id             = 'datamodel';
$project        = "XXXXXXXXXX";

$input          = $_REQUEST['input'];

//$predictionData = new Google_InputInput();  //Depricated method in Google_api_php_client_version1.0.0      // W.P.Roshan
$predictionData = new Google_Service_Prediction_InputInput();
$predictionData->setCsvInstance(array($input));

//$input = new Google_Input();                //Depricated method in Google_api_php_client_version1.0.0 // W.P.Roshan
$input = new Google_Service_Prediction_Input();
$input->setInput($predictionData);

$PredictionResult = $service->trainedmodels->predict($project,$id, $input,$optParams = array());
//print '<h3>Prediction Result:</h3><pre>' . print_r($result, true) . '</pre>';

$AccuracyMetaResult = $service->trainedmodels->get($project, $id, $optParams = array());    
//print '<h3>Classification Accuracy Result:</h3><pre>' . print_r($result, true) . '</pre>';

$stdout                     = new stdClass();
$stdout->dataModel          = $PredictionResult['id'];
$stdout->outputLabel        = $PredictionResult['outputLabel'];
$stdout->negative           = $PredictionResult['modelData']['outputMulti'][0]['score'];
$stdout->neutral            = $PredictionResult['modelData']['outputMulti'][1]['score'];
$stdout->positive           = $PredictionResult['modelData']['outputMulti'][2]['score'];
$stdout->modelCreated       = $AccuracyMetaResult['created'];
$stdout->trainingCompleted  = $AccuracyMetaResult['trainingComplete'];
$stdout->trainingStatus     = $AccuracyMetaResult['trainingStatus'];
$stdout->modelType          = $AccuracyMetaResult['modelData']['modelInfo']['modelType'];
$stdout->dataModelAccuracy  = $AccuracyMetaResult['modelData']['modelInfo']['classificationAccuracy'];

echo json_encode($stdout);

if ($client->getAccessToken()) {
  $_SESSION['token'] = $client->getAccessToken();
} 
sunone5
  • 375
  • 2
  • 5
  • 14
  • If your hosting WHM/CPanel ask them to sync server time with timeserver ( ntp.org - if your hosting using NTP - network time protocol ) if your hosting is on the Virtuozzo VPS ask hosting people to sync VPS with timeserver. @DalmTo - WITHOUT YOUR SUPPORT THIS WILL NOT BE RESOLUTED BIG THANKS DalmTo. – sunone5 Aug 19 '14 at 12:31

3 Answers3

4

I ave just had hours of trying to solve this problem. It turned out that my server's time was a couple of minutes ahead of google's time.

Setting my Server time to the correct time fixed this issue immediately.

Hopefully this helps someone :)

Joel Spencer
  • 129
  • 1
  • 8
  • Can you please elaborate. I installed ntp too on my linux machine, but not able to understand how to solve the problem. I also set my location time to Asia/Kolkata. – Bhupender Keswani Oct 09 '15 at 07:51
2

I think you have a problem with the order of how you are doing things. You are creating the service before you are getting authentication. This is an example using google analytics api.

<?php
session_start();
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';

/************************************************
  The following 3 values an befound in the setting
  for the application you created on  Google 
  Developers console.
  The Key file should be placed in a location
  that is not accessable from the web. outside of 
  web root.

  In order to access your GA account you must
  Add the Email address as a user at the 
  ACCOUNT Level in the GA admin. 
 ************************************************/
$client_id = '1046123799103-nk421gjc2v8mlr2qnmmqaak04ntb1dbp.apps.googleusercontent.com';
$Email_address = '1046123799103-nk421gjc2v8mlr2qnmmqaak04ntb1dbp@developer.gserviceaccount.com';
$key_file_location = '629751513db09cd21a941399389f33e5abd633c9-privatekey.p12';

$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");

$key = file_get_contents($key_file_location);

// seproate additional scopes with a comma
$scopes ="https://www.googleapis.com/auth/analytics.readonly";  

$cred = new Google_Auth_AssertionCredentials(
    $Email_address,
    array($scopes),
    $key
    );

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
    $client->getAuth()->refreshTokenWithAssertion($cred);
}

$service = new Google_Service_Analytics($client);  
$accounts = $service->management_accountSummaries->listManagementAccountSummaries();

//calulating start date
$date = new DateTime(date("Y-m-d"));
$date->sub(new DateInterval('P10D'));

//Adding Dimensions
$params = array('dimensions' => 'ga:userType');
// requesting the data
$data = $service->data_ga->get("ga:78110423", $date->format('Y-m-d'),  date("Y-m-d"), "ga:users,ga:sessions", $params );


?><html>
<?php echo $date->format('Y-m-d') . " - ".date("Y-m-d"). "\n";?>
<table>
<tr>
<?php
//Printing column headers
foreach($data->getColumnHeaders() as $header){  
    print "<td>".$header['name']."</td>";   
}
?>
</tr>
<?php
//printing each row.
foreach ($data->getRows() as $row) {    
    print "<tr><td>".$row[0]."</td><td>".$row[1]."</td><td>".$row[2]."</td></tr>";  
}

//printing the total number of rows
?>
<tr><td colspan="2">Rows Returned <?php print $data->getTotalResults();?> </td></tr>
</table>
</html>
<?php

?>

Example taken from my tutorial Google Service Account php

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • @DalmTo - if Im creating the service before I getting authentication, then why it's properly working on the localhost environment. – sunone5 Aug 19 '14 at 06:34
  • Google_Auth_AssertionCredentials needs to be created first because it is sent to $client then the Service is created using the $client that has its authentication. You are doing it backwards – Linda Lawton - DaImTo Aug 19 '14 at 06:35
  • if I'm doing it backwards why it's working under localhost environment.it's not seems to that matter buddy..but nice try...thanks. – sunone5 Aug 19 '14 at 06:38
  • 2
    Option nr 2: check the server clock make sure it is set correctly. It needs to be in sync with NTP. If its not it thinks there's something wrong with your authentication and you will get a invalid_grant. – Linda Lawton - DaImTo Aug 19 '14 at 06:41
  • Yep that's a kind of acceptable answer but what's NTP ? and how do I sync with my Hosting server time. – sunone5 Aug 19 '14 at 06:46
  • NTP is network time protocol for clock synchronization between computer systems. http://en.wikipedia.org/wiki/Network_Time_Protocol What type of server is it? Just check its time is it the correct? If not set the time. – Linda Lawton - DaImTo Aug 19 '14 at 06:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59561/discussion-between-sunone5-and-daimto). – sunone5 Aug 19 '14 at 06:53
  • I am using @DaImTo's code, but I get the same problem. I have checked the server's clock and it appears to be correct. Any suggestions? – user2768 May 15 '15 at 11:41
  • I'm now following https://developers.google.com/analytics/devguides/reporting/core/v3/quickstart/service-php, which seems to be working. – user2768 May 15 '15 at 12:57
  • DalmTo, yes needs to be in sync with NTP :) Thank you very much [my case was resolved with this](http://serverfault.com/a/368609) – Robin Gomez Sep 09 '15 at 21:19
0

I had same error on my login in page. This error occurs due to re-authentication.

Once you successfully login's to your page. In your code check if Session is set. Otherwise it will go to authenticate user again . That's how I solved my error. Hope it will work for you also.

if(isset($_GET['code'])){<br>
     if(!isset($_SESSION['token'])){
        $gClient->authenticate($_GET['code']);
        $_SESSION['token'] = $gClient->getAccessToken();
    header('location:'.filter_var($redirectURL,FILTER_SANITIZE_URL));
    }
}
sam palve
  • 3
  • 1
  • 5