I am trying to authenticate a service account so that I can use the access token with the client JSON_API library.
I have viewed these articles:
https://code.google.com/p/google-api-php-client/source/browse/trunk/examples/prediction/serviceAccount.php
https://code.google.com/p/google-api-php-client/wiki/UsingTheLibrary
https://developers.google.com/storage/docs/authentication#service_accounts
https://developers.google.com/accounts/docs/OAuth2#scenarios
Here's my PHP Code
<?php
require_once 'google-api-php-client/src/Google_Client.php';
const CLIENT_ID = "";
const SERVICE_ACCOUNT_NAME = "";
const KEY_FILE = "super secret path of course ;)";
$client = new Google_Client();
// Loads the key into PKCS 12 format
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/prediction'),
$key
)
);
$client->setClientId(CLIENT_ID);
$auth = $client->authenticate();
print $auth ? "Returned true" : "Returned false";
print "<br>";
print is_null($client->getAccessToken()) ? "It's null" : "Works";
?>
Here's my output:
Returned true
It's null
I finally figured out how to authenticate using the PHP API library after using a mixture of different resources.
Here's my authentication class for the google php api libray
<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_StorageService.php';
class Model_Storage_Auth
{
const CLIENT_ID = "someuniquenumber.apps.googleusercontent.com";
const SERVICE_ACCOUNT_NAME = "myserviceaccountname#developer.gserviceaccount.com";
const KEY_FILE = "/supersecretpath/key.p12";
const ACCESS_TOKEN = 'access_token';
const APP_NAME = 'My App Name';
private $google_client;
function __construct()
{
$this->google_client = new Google_Client();
$this->google_client->setApplicationName(self::APP_NAME);
}
public function getToken()
{
if(!is_null($this->google_client->getAccessToken())){}
elseif(!is_null(Session::get(self::ACCESS_TOKEN, null)))
{
$this->google_client->setAccessToken(Session::get(self::ACCESS_TOKEN, null));
}
else
{
$scope = array();
$scope[] = 'https://www.googleapis.com/auth/devstorage.full_control';
$key = file_get_contents(self::KEY_FILE);
$this->google_client->setAssertionCredentials(new Google_AssertionCredentials(
self::SERVICE_ACCOUNT_NAME,
$scope,
$key)
);
$this->google_client->setClientId(self::CLIENT_ID);
Google_Client::$auth->refreshTokenWithAssertion();
$token = $this->google_client->getAccessToken();
Session::set(self::ACCESS_TOKEN, $token);
}
return $this->google_client->getAccessToken();
}
}
A couple things to check:
First, I assume that CLIENT_ID and SERVICE_ACCOUNT_NAME are being set to your actual client ID and service account name, not just empty strings, right?
Second, you're using the OAuth scope https://www.googleapis.com/auth/prediction but trying to use that to access GCS. You'll want to either use read-only, read-write, or full-control scope, which you can find here. For example, if you wanted read-write access, you'd use the scope https://www.googleapis.com/auth/devstorage.read_write.
Related
I am creating google client instance and authenticating it once and fetching required data. Afterwards if I want to use that same instance of Google client for some other service , how can I achieve it ?
webmasterMain route is my redirect uri registered in google webmaster .
public function webmasterMain(Request $request)
{
$requestData = $request->all();
if ($request->isMethod('POST') || isset($requestData['code'])) {
$google_redirect_url = env('APP_URL') . '/user/webmasterMain';
$gClient = new \Google_Client();
$gClient->setAccessType("offline");// to get refresh token after expiration of access token
$gClient->setIncludeGrantedScopes(true); // incremental auth
$gClient->setApplicationName(config('services.google.app_name'));
$gClient->setClientId(config('services.google.client_id'));
$gClient->setClientSecret(config('services.google.client_secret'));
$gClient->setRedirectUri($google_redirect_url);
$gClient->setDeveloperKey(config('services.google.api_key'));
$gClient->setScopes(array(
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/webmasters.readonly',
'https://www.googleapis.com/auth/webmasters',
));
$google_oauthV2 = new \Google_Service_Oauth2($gClient);
if ($request->get('code')) {
$gClient->authenticate($request->get('code'));
$request->session()->put('token', $gClient->getAccessToken());
}
if ($request->session()->get('token')) {
$gClient->setAccessToken($request->session()->get('token'));
}
if ($gClient->getAccessToken()) {
$inst = new Google_Service_Webmasters($gClient);
$res = $inst->sites->listSites();
$sites = $res->getSiteEntry();
$siteUrl = [];
foreach ($sites as $key => $site) {
$siteUrl = array_add($siteUrl, $key, ['site_name'=>$site['siteUrl'], 'site_permission_level' => $site['permissionLevel']]);
}
$sites = (((array)$siteUrl));
return view('User::webmasterMain')->with(['data' => $sites]);
} else {
//For Guest user, get google login url
$authUrl = $gClient->createAuthUrl();
return redirect()->to($authUrl);
}
}
return view('User::webmasterMain');
}
Now suppose I want to get the authenticated $gClient for service like Google_Service_Webmasters_SearchAnalyticsQueryRequest , then how can I make $client = $gClient for this next request ?
public function query(Request $request){
//suppose $client is the same instance which was previously authenticated and stored in $gClient
$website = "http://example.com/";
$searchAnalytics = new \Google_Service_Webmasters_SearchAnalyticsQueryRequest();
$searchAnalytics->setStartDate('2017-03-01');
$searchAnalytics->setEndDate('2017-03-31');
$searchAnalytics->setDimensions(['page']);
$searchAnalytics->setSearchType('web');
`$results = $client->searchanalytics->query($website, $searchAnalytics);`
return $results->getRows();
I got the answer , no need to save the instance or do anything but, follow this :
Create a Google Client Object.
At first time authenticating save the accessToken from google client object by getAccessToken().
Use the same access token and set Access token in this google client.
now you can use this google client object for any service.
First time authenticating:
$gClient = new \Google_Client();
//after authenticating
$request->session()->put('token', $gClient->getAccessToken());
Now we can use this access token in any google service call:
$gClient = new \Google_Client();
if ($request->session()->get('token')) {
$gClient->setAccessToken($request->session()->get('token'));
}
$client = new Google_Service_Webmasters($gClient);
I’ve done with google sign-up, I want to ask regarding google token_id authentication. Google issues a token-id to every user which changes on every sign-in, I am getting that token-id when the user sign-in, I want to authenticate that token-id from google to verify if the sign-in was original or fake. I am using this php api provided by google, but it is continuously giving this error:
Uncaught Error: Class 'Silex\Application' not found in C:\xampp\htdocs\final\gplus-verifytoken-php-master\verify.php:23
Stack trace: #0 {main} thrown in C:\xampp\htdocs\final\gplus-verifytoken-php-master\verify.php on line 23
require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__.'/google-api-php-client/src/Google_Client.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
const CLIENT_ID = 'xyz';
const CLIENT_SECRET = 'xyz';
const APPLICATION_NAME = "xyz";
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setClientId(CLIENT_ID);
$client->setClientSecret(CLIENT_SECRET);
$app = new Silex\Application();
$app['debug'] = true;
$app->register(new Silex\Provider\TwigServiceProvider(), array(
'twig.path' => __DIR__,
));
$app->register(new Silex\Provider\SessionServiceProvider());
// Initialize a session for the current user, and render index.html.
$app->get('/', function () use ($app) {
return $app['twig']->render('index.html', array(
'CLIENT_ID' => CLIENT_ID,
'APPLICATION_NAME' => APPLICATION_NAME
));
});
// Verify an ID Token or an Access Token.
// Example URI: /verify?id_token=...&access_token=...
$app->post('/verify', function (Request $request) use($app, $client) {
$id_token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImE0MzY0YjVmYjliODYxYzNhYTRkYTg5NWExMjk5NzZjMjgyZGJmYzIifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiaWF0IjoxNDg1NDEyMjQ1LCJleHAiOjE0ODU0MTU4NDUsImF0X2hhc2giOiJMSV9DTWxzeG1lSTdvQm9lSUxoSjZRIiwiYXVkIjoiNDY4MzU1OTM0NzMzLXZqNnRkdDJtazEwZ3R0OHJvZGY2bG84MHM4czdtdTRrLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTEyNjE1NTE5MDY0MTc3ODI0NTgzIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF6cCI6IjQ2ODM1NTkzNDczMy12ajZ0ZHQybWsxMGd0dDhyb2RmNmxvODBzOHM3bXU0ay5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoibWdoYXphbmZhcmFsaWtoYW4wOUBnbWFpbC5jb20ifQ.Bpa2_zeVebQ7xtKXvuEell50bvUtKOGb5ZertUZGvzGWXnlA-c2kw4Mvko9Xd4JI_R4wbFoyBtrGCiK0jAlJMgaIH8p3wJbzNKPZ-gPFJdX8mv4v42v8-9urGM7rRUCDylz16WEcR1A2qOmEcNCpCf0_FGNpChl8sc8q8zvTnIb_zYYHp_V7ebR2RlUuO2z9G5YzBN3hZDnmen1xLStmNmYKsIiP5ypMqbWaLjnXJjre6bjTuIGymg_phDYDmwWMVTJyx88zmKAfwQTCh2u3qe_fkCDxxm0MO2wC29__q4uc0BfUNdH62GOrNTBJXmPTUZuT1vdUhzz4CLu1KUohWg";
/*$id_token = $request->get("id_token");*/
$access_token = $request->get("access_token");
$token_status = Array();
$id_status = Array();
if (!empty($id_token)) {
// Check that the ID Token is valid.
try {
// Client library can verify the ID token.
$jwt = $client->verifyIdToken($id_token, CLIENT_ID)->getAttributes();
$gplus_id = $jwt["payload"]["sub"];
$id_status["valid"] = true;
$id_status["gplus_id"] = $gplus_id;
$id_status["message"] = "ID Token is valid.";
} catch (Google_AuthException $e) {
$id_status["valid"] = false;
$id_status["gplus_id"] = NULL;
$id_status["message"] = "Invalid ID Token.";
}
$token_status["id_token_status"] = $id_status;
}
$access_status = Array();
if (!empty($access_token)) {
$access_status["valid"] = false;
$access_status["gplus_id"] = NULL;
// Check that the Access Token is valid.
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' .
$access_token;
$req = new Google_HttpRequest($reqUrl);
$tokenInfo = json_decode(
$client::getIo()->authenticatedRequest($req)
->getResponseBody());
if ($tokenInfo->error) {
// This is not a valid token.
$access_status["message"] = "Invalid Access Token.";
} else if ($tokenInfo->audience != CLIENT_ID) {
// This is not meant for this app. It is VERY important to check
// the client ID in order to prevent man-in-the-middle attacks.
$access_status["message"] = "Access Token not meant for this app.";
} else {
$access_status["valid"] = true;
$access_status["gplus_id"] = $tokenInfo->user_id;
$access_status["message"] = "Access Token is valid.";
}
$token_status["access_token_status"] = $access_status;
}
return $app->json($token_status, 200);
});
$app->run();
I did like this
composer install (after that run this command)
composer dump-autoload
it is working for me
If your Framework don't work after migration.
or see Class 'Silex\Application' not found.
Delete "vendor" folder after composer install.
Working for me
I'm using codeigniter 3.x and php 5.5+. I've been trying to get this to work with no luck. I want to call methods inside a youtube controller class I created that will do different things based on communicating with the google or youtube. The problem is with the Google_Client I believe or it's with how to store $client variable maybe so you can use it in second function. When I try calling this from another function it gives a not login required error even thought the user already did the google verification. How can I tell my second function that the user has already done the authorization and got the token. Everything seems to work very well when both functions are in the same function(I mean just using one function). Also I don't want to verify user on every function or method I execute.
So after first function is done, I get redirected with an access token in the url to the second function but then I get an error Message: Error calling GET https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2014-01-01&end-date=2016-01-20&metrics=views&filters=video%3D%3DpC900o6JaMc: (401) Login Required
First function in the controller Youtubeverify:
class Youtubeverify extends CI_Controller{
public function youtube_consent(){
$this->load->library('google');
$OAUTH2_CLIENT_ID = 'MY_ID';
$OAUTH2_CLIENT_SECRET = 'MY_KEY';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes(array('https://www.googleapis.com/auth/yt-analytics-monetary.readonly','https://www.googleapis.com/auth/youtube.readonly'));
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . "/ci/youtubeverify/display_report",
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
$youtubeReporting = new Google_Service_YouTubeReporting($client);
if (isset($_REQUEST['logout'])) {
$this->session->unset_userdata('youtube_token');
}
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$youtube_token = $client->getAccessToken();
//trying to store the access token in a session
$newdata = array('youtube_token'=>$youtube_token);
$this->session->set_userdata($newdata);
header('Location: ' . $redirect);
}
if ($this->session->userdata('youtube_token')) {
$client->setAccessToken($this->session->userdata('youtube_token'));
}
if ($client->getAccessToken()) {
$client->getAccessToken();
}
else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
redirect($authUrl);
}
}
Second function in the controller Youtubeverify:
public function display_report(){
$this->load->library('google');
$client = new Google_Client();
$client->getAccessToken();
$youtubeAnalytics = new Google_Service_YouTubeAnalytics($client);
$id = 'channel==MINE';
$start_date = '2014-01-01';
$end_date = '2016-01-20';
$optparams = array('filters' => 'video==*********');
$metrics = array('views');
$api_response = $metrics;
$api = $youtubeAnalytics->reports->query($id, $start_date, $end_date, $metric,$optparams);
$data['api_response'] = $api_response['views'];
$this->load->view('layouts/mainlay',$data);
}
I have never worked with YouTube API before, but here's a step in the right direction.
class Youtubeverify extends CI_Controller {
// Google API Keys
const CLIENT_ID = '';
const CLIENT_SECRET = '';
// We'll store the client in a class property so we can access it between methods.
protected $Client;
public function __construct () {
parent::__construct();
// setup google client.
$this->Client = new Google_Client();
$this->Client->setClientId(self::CLIENT_ID);
$this->Client->setClientSecret(self::CLIENT_SECRET);
// we call the authenication method for each request
$this->_authenticate_client();
}
// Authentication method
protected function _authenticate_client () {
//if we already have a token then we just set it in the client
//without going through authentication process again
if( $accessToken = $this->session->userdata('youtube_token') ) {
$this->Client->setAccessToken($accessToken);
}else{
// preform authentication as usual with a redirect ...etc
}
}
}
I am working with Google Spreadsheet in PHP. When I use P12 key it works perfect, but when I use JSON key instead of P12 key while Authenticating with Google Spread Sheet, it is giving
Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Unable to load private key'
Please tell me how to use JSON key while Authenticating with Google Spread Sheet in PHP.
Here is the solution I found.
For P12 Key
Normally, we use the following code to generate a token.
public static function getToken()
{
$key = file_get_contents( APPLICATION_DIR.'/'.APPLICATION_GOOGLE_CLIENT_KEY_FILE);
$cred = new Google_Auth_AssertionCredentials(
APPLICATION_GOOGLE_CLIENT_EMAIL,
array('https://spreadsheets.google.com/feeds'),
$key
);
$client = new Google_Client();
$client->setAssertionCredentials($cred);
if (!$client->getAuth()->isAccessTokenExpired()) {
return false;
}
else {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service_token = json_decode($client->getAccessToken());
return $service_token->access_token;
}
For JSON Key
But now we don't have P12 key, we have a JSON key, so I just made some changes in the above code, please take a look below:
public static function getToken()
{
$key = APPLICATION_DIR.'/'.APPLICATION_GOOGLE_CLIENT_KEY_FILE;
$data = json_decode(file_get_contents($key)); // here i decoded the json
if (isset($data->type) && $data->type == 'service_account') {
$cred = new Google_Auth_AssertionCredentials(
APPLICATION_GOOGLE_CLIENT_EMAIL, // it's the client email
array('https://spreadsheets.google.com/feeds'), // it's google spreadsheet scope
$data->private_key // here is the private key
);
}
$client = new Google_Client();
$client->setAssertionCredentials($cred);
if (!$client->getAuth()->isAccessTokenExpired()) {
return false;
}
else {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service_token = json_decode($client->getAccessToken());
return $service_token->access_token;
}
Access token will only be valid 1 hour and is sent as decoded json. So you probably have to decode it first.
$token = json_decode($client->getAccessToken());
$serviceRequest = new DefaultServiceRequest($token->access_token);
ServiceRequestFactory::setInstance($serviceRequest);
Using p12 key should work fine then.
session_start();
define('GOOGLE_CLIENT_ID','');
define('GOOGLE_CLIENT_EMAIL','');
define('GOOGLE_SPREADSHEETS_SCOPE','https://spreadsheets.google.com/feeds');
define('GOOGLE_APPLICATION_NAME','whatever');
define('GOOGLE_KEY_FILE','xxxxxxxxxxxxxx.p12'); // pass for key: notasecret
function getToken()
{
$client = new Google_Client();
$client->setApplicationName(GOOGLE_APPLICATION_NAME);
$client->setClientId(GOOGLE_CLIENT_ID);
$key = file_get_contents(GOOGLE_KEY_FILE);
$cred = new Google_Auth_AssertionCredentials(
GOOGLE_CLIENT_EMAIL,
array(GOOGLE_SPREADSHEETS_SCOPE),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$service_token = json_decode($client->getAccessToken());
return $service_token->access_token;
}
require("vendor/autoload.php");
use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;
$_SESSION['access_token']=getToken();
$serviceRequest = new Google\Spreadsheet\DefaultServiceRequest($_SESSION['access_token']);
Google\Spreadsheet\ServiceRequestFactory::setInstance($serviceRequest);
$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
I am running the following PHP code, using the client libraries found here: https://code.google.com/p/google-api-php-client/. I do not get any errors for any of this code, but when I call getAccessToken(), it returns null.
I have allowed access to this service account on my personal calendar, and have granted full access to the project via the API Console.
Any ideas?
require_once 'google-api-php-client/src/Google_Client.php';
const CLIENT_ID = 'blahblahblah';
const SERVICE_ACCOUNT_NAME = 'blahblahblah#developer.gserviceaccount.com';
const KEY_FILE = 'path/to/privatekey.p12';
$google_client = new Google_Client(); // created only to initialized static dependencies
$client = new Google_OAuth2(); // you really just need Google_OAuth2
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(
new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar'),
$key
)
);
var_dump($client->getAccessToken());
For some reason, this seemed to work:
require_once 'google-api-php-client/src/Google_Client.php';
const CLIENT_ID = 'blahblahblah';
const SERVICE_ACCOUNT_NAME = 'blahblahblah#developer.gserviceaccount.com';
const KEY_FILE = 'path/to/privatekey.p12';
const CALENDAR_SCOPE = "https://www.googleapis.com/auth/calendar";
$key = file_get_contents(KEY_FILE);
$auth = new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array(CALENDAR_SCOPE),
$key
);
$client = new Google_Client();
$client->setScopes(array(CALENDAR_SCOPE));
$client->setAssertionCredentials($auth);
$client->getAuth()->refreshTokenWithAssertion();
$accessToken = $client->getAccessToken();
$client->setClientId(CLIENT_ID);
If someone can explain why this worked, please edit this answer or comment!