I followed the tutorial on the google drive, it says that to persist the authentication/access token we have to use refresh token, so that we don't have to ask user to authenticate/authorize every time we make an API call.
Code:
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
$client = new Google_Client();
// Get your credentials from the console
$client->setClientId('client ID');
$client->setClientSecret('client secret');
$client->setRedirectUri('URL');
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
$client->setAccessType('offline');
$service = new Google_DriveService($client);
$authUrl = $client->createAuthUrl();
// Exchange authorization code for access token
$accessToken = $client->authenticate();
$client->setAccessToken($accessToken);
$files = $service->files->listFiles();
echo "<pre>"; print_r($files);
This gives me the list of files and folders, but every time I refresh the page it takes me back to google authorization page. I can save the access token in database but how to use that and make API calls without again asking authorization from the user??
Any thoughts??
Thanks,
Aniket
Probably, it's better to use Server to Server authentication by using P12 key:
https://developers.google.com/api-client-library/php/auth/service-accounts
You can impersonate a user account and all files will be accessible by your server.
$client_email = '1234567890- a1b2c3d4e5f6g7h8i#developer.gserviceaccount.com';
$private_key = file_get_contents('MyProject.p12');
$user_to_impersonate = 'user#example.org';
$private_key = file_get_contents($pkey); //notasecret
$scopes = array('https://www.googleapis.com/auth/drive');
$credentials = new \Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key,
'notasecret', // Default P12 password
'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
$user_to_impersonate
);
$client = new \Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
$service = new \Google_Service_Drive($client);
$files = $service->files->listFiles();
echo "count files=".count($files)."<br>";
foreach( $files as $item ) {
echo "title=".$item['title']."<br>";
}
This will give you all files listed in your Google Drive without any client user interaction.
Related
I have a Wordpress site (running PHP) that needs to display its own analytics data to visitors using the google-api. I want to create the charts in Javascript, so I need to fetch an auth token from the PHP code and then pass that to the Javascript code. I can't figure out how to get the auth token.
So far, I have code similar to this working using my service account:
https://github.com/google/google-api-php-client/blob/master/examples/service-account.php
My code:
$client = new Google_Client();
$client->setAuthConfig($credentialsFilePath);
$client->addScope('https://www.googleapis.com/auth/analytics.readonly');
$client->setApplicationName("GoogleAnalytics");
$analytics = new Google_Service_Analytics($client);
$ga = $analytics->data_ga;
$start = date('Y-m-d', strtotime('-7 days'));
$end = date('Y-m-d');
$views = $ga->get('ga:'.$myAnalyticsId,
$start,
$end,
'ga:pageviews,ga:sessions,ga:newUsers',
array(
'dimensions' => 'ga:date',
'sort' => 'ga:date'
));
This all works, and I'm able to connect to Google_Service_Analytics and fetch analytics data. However, I can't figure out how to fetch a service access token using my credentials, that I can hand off to the Javascript code so I can use the Google Analytics API from Javascript.
This doesn't work:
$token = $client->getAccessToken();
Token just ends up being null. What do I need to do to fetch a token?
Here is the working code for me.
The service account has a different type of process for generating access token.
It is not following oauth client api.
//include_once 'vendor/autoload.php';
$credentialsFilePath = 'test.json';
$client = new Google_Client();
$client->setAuthConfig($credentialsFilePath);
$client->addScope('https://www.googleapis.com/auth/analytics.readonly');
$client->setApplicationName("GoogleAnalytics");
$client->refreshTokenWithAssertion();
$token = $client->getAccessToken();
print_r($token);
$accessToken = $token['access_token'];
Figured this out:
$client->refreshTokenWithAssertion();
$token = $client->getAccessToken();
$accessToken = $token['access_token'];
First answer still works in 2021 (Thanks!), but a used function is deprecated (still available though)
This worked for me
public function getToken() {
$client = new Client(); // use Google\Client;
$client->setAuthConfig('securejsonfile.json');
$client->addScope('https://www.googleapis.com/auth/cloud-platform');
$client->setApplicationName('appname');
$client->fetchAccessTokenWithAssertion();
return $client->getAccessToken(); //array
}
I have next code for google auth
use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;
require './vendor/autoload.php';
$application_name = '*****';
$client_secret = '**********';
$client_id = '**********.apps.googleusercontent.com';
$scope = array('https://spreadsheets.google.com/feeds');
$key = file_get_contents(__DIR__.'/the_key.txt');
$client = new Google_Client();
$client->setApplicationName($application_name);
$client->setClientId($client_id);
$client->setAccessType('offline');
$client->setAccessToken($key);
$client->setScopes($scope);
$client->setApprovalPrompt('force');
$client->setClientSecret($client_secret);
if ($client->getAccessToken()) {
if($client->isAccessTokenExpired()) {
$newToken = json_encode($client->getAccessToken());
$token = $client->getAccessToken();
$client->refreshToken($token['refresh_token']);
json_encode($client->getAccessToken()));
}
$key = json_decode(file_get_contents(__DIR__.'/the_key.txt'));
First time fillin file via oauthcallback via browser, and it works ok, i got refresh token and all works ok.
But when token expires as you see in code i request new via refresh_token, but in result i didn't get new refresh_token.
Also i forced acces type to offline, and approval prompt to force in Client.php of google-oauth-client(because even if i set it via paramaters it didn't worked).
My script must be executed via cron. So i can't each time receive token manually. Can you help me with this?
For credentials, I have created an developer account on https://console.developers.google.com, I have created a project and then i have created credentials from API Manager. I use "google/apiclient": "1.1.*" package. I think it is a problem with credentials.
$OAUTH2_CLIENT_ID = 'XXXXX-rvm1l9b1nvht9je1ic0bbe05ab5gvhbg.apps.googleusercontent.com';
$OAUTH2_CLIENT_SECRET = 'XXXXXXP90L_DLD3Nrc_rT4zGD';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = url('/');
$client->setRedirectUri($redirect);
$token = $client->getAccessToken();
dd($token);
Tip:
Don't use:
$client->authenticate($authcode);
$token = $client->getAccessToken();
Use:
$token = $client->fetchAccessTokenWithAuthCode($authcode);
This will at least allow you to see the error message if you dump $token.
In the 'Don't use:' example, if the authenticate() step fails, getAccessToken() may return null. Bad job on the API here.
I think the problem is you're not making the request to Google to authenticate and get back the token. You should do:
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = url('/');
$client->setRedirectUri($redirect);
//redirect to google server to get the token
return Redirect::to( $client->createAuthUrl() );
If the authentication succeeds, google will redirect you to the page you set with $client->setRedirectUri($redirect).
In that page you can:
//authenticate using the parameter $_GET['code'] you got from google server
$client->authenticate( $request->input('code') );
//get the access token
$tokens = $client->getAccessToken();
I am getting the following error when attempting to access my Google Analytics data: exception 'Google_Service_Exception' with message 'Error calling GET ...my query...': (401) login required
I'm not sure how to fix this, and I've already spent hours trying to set this up with no success.
Here's my code:
$client = new \Google_Client();
$client->setApplicationName("My App");
$client->setDeveloperKey('my API key');
$analytics = new \Google_Service_Analytics($client);
$OBJresult = $analytics->data_ga->get(
'ga:myprofileid' .,
'2012-01-01',
date("Y-m-d"),
'ga:visits',
array(
'filters' => 'ga:pagePath==/home',
'dimensions' => 'ga:pagePath',
'metrics' => 'ga:pageviews',
'sort' => '-ga:pageviews'
)
);
If you are only accessing your own data then you should go with a service account. If you want to be able to login and see other peoples data then you should use Oauth2.
service account Example:
<?php
require_once 'Google/autoload.php';
session_start();
/************************************************
The following 3 values an befound in the setting
for the application you created on Google
Developers console. Developers console.
The Key file should be placed in a location
that is not accessable from the web. outside of
web root. 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 = '[Your client id]';
$Email_address = '[YOur Service account email address Address]';
$key_file_location = '[Locatkon of key file]';
$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);
//Adding Dimensions
$params = array('dimensions' => 'ga:userType');
// requesting the data
$data = $service->data_ga->get("ga:89798036", "2014-12-14", "2014-12-14", "ga:users,ga:sessions", $params );
?>
<html>
Results for date: 2014-12-14<br>
<table border="1">
<tr>
<?php
//Printing column headers
foreach($data->getColumnHeaders() as $header){
print "<td><b>".$header['name']."</b></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>";
}
?>
<tr><td colspan="2">Rows Returned <?php print $data->getTotalResults();?> </td></tr>
</table>
</html>
Helpful Links:
Code ripped from Service account tutorial
Google Analytics oauth2 tutorial
Google's new official tutorial Hello Analytics php
The code shown does not authenticate anywhere.
I am not an expert on this API, but according to this link you are missing some of the following options.
$client = new Google_Client();
$client->setAccessType('online'); // default: offline
$client->setApplicationName('My Application name');
$client->setClientId('INSERT HERE');
$client->setClientSecret('INSERT HERE');
$client->setRedirectUri($scriptUri);
$client->setDeveloperKey('INSERT HERE'); // API key
The accepted answer didn't work for my service account. What worked instead:
Create a service account at IAM & Admin panel. Make sure to get the key file in JSON format.
Download that key file to a location reachable from your script (but not reachable from the Web!)
Run the following code:
$service_url = "https://www.googleapis.com/auth/analytics.readonly";
$client = new Google_Client();
$client->setAuthConfigFile($key_file_location); // path to your json key file
$client->addScope($service_url); // URL to the service you're planning to use
// Run your queries here
DalmTo's answer did the trick for me, but if you don't want to hardcode $client_id and such you can simplify it a bit:
public function __construct() {
$this->client = new Google_Client();
$credentials = $this->client->loadServiceAccountJson(__DIR__.'/../../google-service-account.json', [Google_Service_Calendar::CALENDAR]);
$this->client->setAssertionCredentials($credentials);
if($this->getAuth()->isAccessTokenExpired()) {
$this->getAuth()->refreshTokenWithAssertion($credentials);
}
}
/**
* #return \Google_Auth_OAuth2
*/
public function getAuth() {
return $this->client->getAuth();
}
Where google-service-account.json is the key file they give you when you create your service account. It looks like this:
{
"type": "service_account",
"project_id": "xxxxxxxxxx",
"private_key_id": "xxxxxxxxxxxxxxxxxxx",
"private_key": "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----\n",
"client_email": "xxxxxxxxxx#xxxxxxx.iam.gserviceaccount.com",
"client_id": "xxxxxxxxxxxxxxx",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xxxxxxxx.iam.gserviceaccount.com"
}
I am aware many similar questions have been asked, but I am struggling to understand. I have successfully used the php google libraries for v3 to interface with calendar functions. The code I have is:
<?php
require_once "google-api-php-client/autoload.php";
session_start();
$client = new Google_Client();
$client->setApplicationName("My app");
$client->setClientId("CI.apps.googleusercontent.com");
$client->SetClientSecret("SECRET");
$client->setRedirectUri("redirect");
$client->setDeveloperKey("key");
$client->setScopes(array("https://www.googleapis.com/auth/calendar"));
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);//update token
}
$service=new Google_Service_Calendar($client);
...
?>
This works ok, but the calendar I want to modify is always the same- the app is registered at the same account as the calendar. Is there a way round the oauth2 authentication so that I can just adjust the entries in the calendar which I own without having to perform an extra authentication step with redirect? I used to use Zend to do this and it worked fine until recently, but updating to v3 of the API and using oauth2 like this seems a bit overkill. I may have misunderstood of course - any help of advice would me most helpful.
Ok - in case anyone else searches for the answer to this I thought I'd post my solution. I was a bit stupid. If you want to authenticate an application to modify a calendar in this way you need to create a service account in the google console - not a web application. Then you need to use the service account name (e-mail address given to the Client ID for the service account) to allow the script to modify the calendar. Do this manually by going to the setting of the calendar you want to modify. This code will then work fine.
<?php
session_start();
require_once "google-api-php-client/autoload.php";
$client_id = ''; //Client ID
$service_account_name = ''; //Email Address
$key_file_location = ''; //key.p12
$client = new Google_Client();
$client->setApplicationName("my app");
$service = new Google_Service_Calendar($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,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();?>