Unable to list the events and received error 404 - php

I tried this code, but it doesn't show any result and I checked my error log it says 404 not found.
I tried using another method it say missing scope.
<?php
session_start();
error_reporting(E_ALL);
require_once "Google/Client.php";
require_once "Google/Service/Calendar.php";
$client = new Google_Client();
/************************************************
ATTENTION: Fill in these values! Make sure
the redirect URI is to this page, e.g:
http://localhost:8080/user-example.php
************************************************/
$client_id = '';
$client_secret = '';
$redirect_uri = 'http://localhost/listgoogleuser.php';
/************************************************
Make an API request on behalf of a user. In
this case we need to have a valid OAuth 2.0
token for the user, so we need to send them
through a login flow. To do this we need some
information from our API console project.
************************************************/
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/calendar");
$service = new Google_Service_Calendar($client);
/************************************************
If we're logging out we just need to clear our
local access token in this case
************************************************/
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
/************************************************
If we have a code back from the OAuth 2.0 flow,
we need to exchange that with the authenticate()
function. We store the resultant access token
bundle in the session, and redirect to ourself.
************************************************/
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 we have an access token, we can make
requests, else we generate an authentication URL.
************************************************/
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
} else {
$authUrl = $client->createAuthUrl();
}
$events = $service->events->listEvents('URL HERE');
foreach($events['items'] as $datauser){
echo $datauser['summary'];
}
?>

I was having the same issues, though for me every method I was trying was ending up not working so to kill two birds with one stone I started over and used the code you provided above. I removed these lines of code:
$events = $service->events->listEvents('URL HERE');
foreach($events['items'] as $datauser){
echo $datauser['summary'];
}
And added this at the very end and I was able to get a response.
<div class="box">
<div class="request">
<?php if (isset($authUrl)): ?>
<a class='login' href='<?php echo $authUrl; ?>'>Connect Me!</a>
<?php else: ?>
<?
$calendarList = $service->calendarList->listCalendarList();
while(true) {
foreach ($calendarList->getItems() as $calendarListEntry) {
echo $calendarListEntry->getSummary()." | ".$calendarListEntry->getId()."<br/>";
}
$pageToken = $calendarList->getNextPageToken();
if ($pageToken) {
$optParams = array('pageToken' => $pageToken);
$calendarList = $service->calendarList->listCalendarList($optParams);
} else {
break;
}
}
?>
<a class='logout' href='?logout'>Logout</a>
<?php endif ?>
</div>
<?php if (isset($short)): ?>
<div class="shortened">
<?php var_dump($short); ?>
</div>
<?php endif ?>
</div>
Also at the top of your page you call $client = new Google_Client(); twice.

Related

Why does isset($_GET['code']) returning false while using google oauth login in php?

include ("header.php") ;
require_once 'vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->setRedirectUri('http://localhost/ecommerce/index.php');
$client->addScope('email');
$client->addScope('profile');
$login_button=' <div class="col-sm-4">
<div class="card">
<div class="card-body">
<a class="btn btn-social btn-google" href="'.$client->createAuthUrl().'" role="button">
<i class="fab fa-google"></i>
Sign in with Google
</a>
</div>
</div>
</div>';
if(isset($_GET['code'])){
$token=$client->fetchAccessTokenWithAuthCode($_GET['code']);
if(!isset($token['error'])){
$client->setAccessToken($token['access_token']);
$_SESSION['access_token']=$token['access_token'];
$google_service=new Google_Service_Oauth2($client);
$data=$google_service->userinfo->get();
if(!empty($data['given_name'])){
$_SESSION['uid']=$data['given_name'];
}
if(!empty($data['family_name'])){
$_SESSION['user_last_name']=$data['family_name'];
}
if(!empty($data['gender'])){
$_SESSION['gender']=$data['gender'];
}
}
}
?>
My code does not enter the if block: isset($_GET['code']) is returning false.
I want access to just the user name and gender.
I have installed composer and google api client 2.0.
Its not set probably because you haven't called auth yet. Code is only set after the user has clicked the consent screen and then it will never ben used again.
oauth2callback.php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Oauth2Authentication.php';
// Start a session to persist credentials.
session_start();
// Handle authorization flow from the server.
if (! isset($_GET['code'])) {
$client = buildClient();
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client = buildClient();
$client->authenticate($_GET['code']); // Exchange the authencation code for a refresh token and access token.
// Add access token and refresh token to seession.
$_SESSION['access_token'] = $client->getAccessToken();
$_SESSION['refresh_token'] = $client->getRefreshToken();
//Redirect back to main script
$redirect_uri = str_replace("oauth2callback.php",$_SESSION['mainScript'],$client->getRedirectUri());
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
Oauth2Authentication.php
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}

(401) Unauthorized when trying to insert a moment using the Google+ API

Using code below I successfully received a token and using this token also get user detail, but when I try to post/insert moment in user wall I see the following error message
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST https:--www.googleapis.com/plus/v1/people/me/moments/vault: (401) Unauthorized' in $_SESSION['access_token_gp']
I got user token when user login using my site in login page I ask for below permission
$client->addScope("email");
$client->addScope("https://www.googleapis.com/auth/plus.stream.write");
$client->addScope("https://www.googleapis.com/auth/plus.login");
If I print_r($tokenInfo); you will see all scope which I ask at login time.
The full code:
session_start();
require_once realpath(dirname(__FILE__) . '/google-api-php-client-master/autoload.php');
$client_id = 'my_client_id';
$client_secret = 'my_secret_key';
$redirect_uri = 'my_redirect_url';
// code to post in google plus start here //
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
if (isset($_SESSION['access_token_gp'])) {
// Verify the token
$token = json_decode($_SESSION['access_token_gp']);
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$token->access_token;
$req = new Google_Http_Request($reqUrl);
$tokenInfo = get_object_vars(json_decode($client->getAuth()->authenticatedRequest($req)->getResponseBody()));
if($tokenInfo['expires_in'] <= 0){
$client->authenticate($_SESSION['access_token_gp']);
$_SESSION['access_token_gp'] = $client->getAccessToken();
} else {
$client->setAccessToken($_SESSION['access_token_gp']);
}
$plusservicemoment = new Google_Service_Plus_Moment();
$plusservicemoment->setType("http://schemas.google.com/AddActivity");
$plusService = new Google_Service_Plus($client);
$item_scope = new Google_Service_Plus_ItemScope();
$item_scope->setId($tokenInfo['user_id']);
$item_scope->setType("http://schemas.google.com/AddActivity");
$item_scope->setName("The madexme Platform");
$item_scope->setDescription("A page that describes just how madexme is work!");
//$item_scope->setImage("full image path here");
$plusservicemoment->setTarget($item_scope);
$result = $plusService->moments->insert('me','vault',$plusservicemoment);
//print_r($result);
}
// code to post in google plus end here //
Make sure you have the latest client lib from GitHub. There is something wrong with your Oauth2 connection. This code is partially converted from my Google Google Calendar API tutorial. I don't have the power to test it right now. But this should be close. I will test it tonight.
<?php
require_once 'Google/Client.php';
require_once 'Google/Service/Plus.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("AIzaSyBBH88dIQPjcl5nIG-n1mmuQ12J7HThDBE");
$client->setClientId('2046123799103-i6cjd1hkjntu5bkdkjj5cdnpcu4iju8p.apps.googleusercontent.com');
$client->setClientSecret('6s4YOx3upyJhtwnetovfK40e');
$client->setRedirectUri('http://localhost/google-api-php-client-samples/Calendar/oauth2Pure.php');
$client->setAccessType('offline'); // Gets us our refreshtoken
$client->setScopes(array(https://www.googleapis.com/auth/plus.login'));
//For loging out.
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
// Step 2: The user accepted your access now you need to exchange it.
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));
}
// Step 1: The user has not authenticated we give them a link to login
if (!isset($_SESSION['token'])) {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
// Step 3: We have access we can now create our service
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
print "<a class='logout' href='".$_SERVER['PHP_SELF']."?logout=1'>LogOut</a><br>";
$service = new Google_Service_Plus($client);
$moment = new Google_Moment();
$moment->setType('http://schemas.google.com/AddActivity');
$itemScope = new Google_ItemScope();
$itemScope->setUrl('https://developers.google.com/+/plugins/snippet/examples/thing');
$moment->setTarget($itemScope);
$plus->moments->insert('me', 'vault', $moment);
?>
Again I hope you understand that this is not going to show up on the users Google+ page / timeline.

Wrong number of segments in token (OAuth Google Api)

My end goal is to send email to myself via Google Gmail API.
And here is my problem.
When i'm getting my access token an error pops up
Fatal error: Uncaught exception 'Google_Auth_Exception' with message 'Wrong number of segments in token: '
I read here Cloud endpoints oauth2 error that "This DOES NOT mean your token was invalid", but i'm getting a fatal error that interrupting my script.
My access token looks like this 4/MqiIIl5K4S3D4iiieHshQt5D4M79oo07SbhMn22oe2o.cswa8t9ZuDAfJvIeHux6iLYXpNQmlAI
If I refresh the page with this token i'd get another error, which is
'Error fetching OAuth2 access token, message: 'invalid_grant: Invalid code.'
Here is my code
<?php
include_once "templates/base.php";
echo pageHeader("Simple API Access");
require_once realpath(dirname(__FILE__) . '/../autoload.php');
$client = new Google_Client();
$client_id = '114600397795-j5sn0gvsdrup0s8dcmsj49iojp3m9biu.apps.googleusercontent.com';
$client_secret = 'm3Dzankql_rs1OGICsA3Hbtc';
$redirect_uri = 'http://alupa.com/gmail/examples/simple-query.php';
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/gmail.readonly");
$client->addScope("https://mail.google.com/");
$apiKey = "AIzaSyCWXxrTshKsotxEYNZZCXxdVXhLeku55cw";
$client->setDeveloperKey($apiKey);
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));
}else{
$client->setApplicationName("Client_Gmail_Examples");
}
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
} else {
$authUrl = $client->createAuthUrl();
}
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
$token_data = $client->verifyIdToken()->getAttributes();
}
?>
<div class="box">
<div class="request">
<?php
if (isset($authUrl)) {
echo "<a class='login' href='" . $authUrl . "'>Connect Me!</a>";
} else {
echo "<a class='logout' href='?logout'>Logout</a>";
}
?>
</div>
</div>
alupa.com is my local domain and I don't see any problems with that
I'm using original library from google https://github.com/google/google-api-php-client
Change:
$token_data = $client->verifyIdToken()->getAttributes();
to:
$tuan = $client->getAccessToken();
$token_data = $client->verifyIdToken($tuan->id_token);
You need to add the scope openid and then you get an id_token as well as the access token. You then use the id token with $client->verifyIdToken

Google OAuth 2.0 refresh token for web application with public access

I'm getting the following error:
The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved
I have a web application which only my server will be accessing, the initial auth works fine, but after an hour, the aforementioned error message pops up. My script looks like this:
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("{MY_API_KEY}");
$client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com');
$client->setClientSecret('{MY_KEY}');
$client->setRedirectUri('{MY_REDIRECT_URI}');
$client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
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));
}
if (!$client->getAccessToken() && !isset($_SESSION['token'])) {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
How can I set up a refresh token for this?
Edit 1: I've tried doing this with a Service account as well. I followed the documentation available on GitHub:
https://github.com/google/google-api-php-client/blob/master/examples/service-account.php
My script looks like this:
session_start();
include_once "templates/base.php";
require_once 'Google/Client.php';
require_once 'Google/Service/Gmail.php';
$client_id = '{MY_CLIENT_ID}.apps.googleusercontent.com';
$service_account_name = '{MY_EMAIL_ADDRESS}#developer.gserviceaccount.com ';
$key_file_location = 'Google/{MY_KEY_FILE}.p12';
echo pageHeader("Service Account Access");
if ($client_id == ''
|| !strlen($service_account_name)
|| !strlen($key_file_location)) {
echo missingServiceAccountDetailsWarning();
}
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$service = new Google_Service_Gmail($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/gmail.readonly'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
This returns the following message:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }''
After tracking this code to it's source, which can be found in Google/Auth/OAuth2.php
The method in question, refreshTokenRequest:
private function refreshTokenRequest($params)
{
$http = new Google_Http_Request(
self::OAUTH2_TOKEN_URI,
'POST',
array(),
$params
);
$http->disableGzip();
$request = $this->client->getIo()->makeRequest($http);
$code = $request->getResponseHttpCode();
$body = $request->getResponseBody();
if (200 == $code) {
$token = json_decode($body, true);
if ($token == null) {
throw new Google_Auth_Exception("Could not json decode the access token");
}
if (! isset($token['access_token']) || ! isset($token['expires_in'])) {
throw new Google_Auth_Exception("Invalid token format");
}
if (isset($token['id_token'])) {
$this->token['id_token'] = $token['id_token'];
}
$this->token['access_token'] = $token['access_token'];
$this->token['expires_in'] = $token['expires_in'];
$this->token['created'] = time();
} else {
throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code);
}
}
Which means that the $code variable is NULL.
I found this post on SO:
Error refreshing the OAuth2 token { “error” : “invalid_grant” }
And can see that there is still no prefered solution. This is driving me nuts. There is very little to no documentation available on this and if anybody has a solution, I'm sure I'm not the only one looking for it.
Each access_token expires after a few seconds and need to be refreshed by refresh_token, "Offline access" is what you are looking for. Here you can follow the documentation:
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
To obtain a refresh_token you have to run this code only one time:
require_once 'Google/Client.php';
$client = new Google_Client();
$client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com');
$client->setClientSecret('{MY_KEY}');
$client->setRedirectUri('{MY_REDIRECT_URI}');
//next two line added to obtain refresh_token
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
if (isset($_GET['code'])) {
$credentials = $client->authenticate($_GET['code']);
/*TODO: Store $credentials somewhere secure */
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
$credentials includes an access token and a refresh token. You have to store this to obtain new access tokens at any time. So when you wanted to make a call to api:
require_once 'Google/Client.php';
require_once 'Google/Service/Gmail.php';
/*TODO: get stored $credentials */
$client = new Google_Client();
$client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com');
$client->setRedirectUri('{MY_REDIRECT_URI}');
$client->setClientSecret('{MY_KEY}');
$client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
$client->setAccessToken($credentials);
$service = new Google_Service_Gmail($client);

"insufficient permissions" when trying to get Google Spreadsheet meta info

I'll be needing to add data to an existing ~1000-record spreadsheet row by row soon. I thought I want to make my life easier by making a small PHP page that would show me a row's data and provide me with a form to add the data I want to that row. the spreadsheet is in Drive so that leads me to the Drive API! :)
I've downloaded the Google API client manager and got to work with the OAuth 2.0 example (that shortens a URL). That all worked great, but now I'm trying to fetch some metadata off the spreadsheet that I need. No matter which kind of call I use regarding drive, I always get the following error:
Fatal error: Uncaught exception 'Google_Service_Exception' with message 'Error calling POST https://www.googleapis.com/drive/v2/files: (403) Insufficient Permission'
Any idea what might cause this? For reference, here's my code:
<?php
session_start();
set_include_path("google-api-php-client-master/src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Drive.php';
$client_id = 'xxx';
$client_secret = 'xxx';
$redirect_uri = 'http://localhost/coding/';
//SETTING UP THE CLIENT
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope('https://www.googleapis.com/auth/drive');
$client->addScope('https://spreadsheets.google.com/feeds');
$service = new Google_Service_Drive($client);
//QUICK LOGOUT MECHANISM
if (isset($_REQUEST['logout'])) {
unset($_SESSION['access_token']);
}
//HANDLE OAUTH
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['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
} else {
$authUrl = $client->createAuthUrl();
}
//TALK TO DRIVE
if ($client->getAccessToken()) {
//THIS GOES WRONG :)
$service->files->get('xxx');
}
if (isset($authUrl)): ?>
<a class='login' href='<?php echo $authUrl; ?>'>Connect Me!</a>
<?php else: ?>
<a class='logout' href='?logout'>Logout</a>
<?php endif ?>
Turns out only the Drive API was enabled in the developer console, not the SDK. Thanks!

Categories