Wrong number of segments in token (OAuth Google Api) - php

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

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();
}
}

Google Drive API with PHP - Problems with refresh token getting message 'refresh token must be passed in or set as part of setAccessToken'

I'm trying to refresh token on my PHP script but It's not working yet. I'm using Google Drive API with PHP, my script works great in browser until token expires, checking in other sites I changed the code in this way:
index.php
<?php
require_once 'vendor/autoload.php';
if (!file_exists("client_id.json")) exit("Client secret file not found");
$client = new Google_Client();
$client->setAuthConfig('client_id.json');
$client->addScope(Google_Service_Drive::DRIVE);
if (file_exists("credentials.json")) {
$access_token = (file_get_contents("credentials.json"));
$client->setAccessToken($access_token);
//Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$refreshTokenSaved = $client->getRefreshToken();
$client->fetchAccessTokenWithRefreshToken($refreshTokenSaved);
$accessTokenUpdated = $client->getAccessToken();
$accessTokenUpdated['refresh_token'] = $refreshTokenSaved;
file_put_contents("credentials.json", json_encode($accessTokenUpdated));
//I also tried in this way but it's also not working:
//$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
//file_put_contents("credentials.json", json_encode($client->getAccessToken()));
}
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getFiles(); //http://stackoverflow.com/questions/37975479/call-to-undefined-method-google-service-drive-filelistgetitems
echo json_encode($files_list);
} else {
$redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . '/drive/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
oauth2callback.php
<?php
require_once 'vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfigFile('client_id.json');
$client->setRedirectUri('https://' . $_SERVER['HTTP_HOST'] . '/drive/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE); //::DRIVE_METADATA_READONLY
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$access_token = $client->getAccessToken();
file_put_contents("credentials.json", json_encode($access_token));
$redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . '/';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
But I still receive the message in logs:
PHP Fatal error: Uncaught exception 'LogicException' with message 'refresh token must be passed in or set as part of setAccessToken' in /var/www/drive/vendor/google/apiclient/src/Google/Client.php:266\nStack trace:\n#0 /var/www/drive/index.php(14): Google_Client->fetchAccessTokenWithRefreshToken(NULL)\n#1 {main}\n thrown in /var/www/drive/vendor/google/apiclient/src/Google/Client.php on line 266
I have to delete credentials.json and generate a new one executing index.php and being redirected to oauth2callback.php each hour, but that's not the idea.
How can I fix it?
I'd like to receive your help.
Finally the token refresh works, I had to add this line $client->setAccessType("offline"); in oauth2callback.php, also delete and generate a new client_id.json to avoid errors.
<?php
require_once 'vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfigFile('new_client_id.json');
$client->setRedirectUri('https://' . $_SERVER['HTTP_HOST'] . '/drive/resp.php');
$client->addScope(Google_Service_Drive::DRIVE); //::DRIVE_METADATA_READONLY
$client->setAccessType("offline");
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$access_token = $client->getAccessToken();
file_put_contents("credentials.json", json_encode($access_token));
$redirect_uri = 'https://' . $_SERVER['HTTP_HOST'] . '/drive';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>

"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!

Granting Access For Blogger in OAUTH 2

I am new to Google Oauth 2.I saw google documentation and got the below php library
<?php
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_PlusService.php';
session_start();
$client = new Google_Client();
$client->setApplicationName('Google+ PHP Starter Application');
$client->setClientId('...');
$client->setClientSecret('....');
$client->setRedirectUri('http://photoapp.biz/0/blogger/test.php');
$client->setDeveloperKey('....');
$plus = new Google_PlusService($client);
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['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']);
}
if ($client->getAccessToken()) {
$activities = $plus->activities->listActivities('me', 'public');
print 'Your Activities: <pre>' . print_r($activities, true) . '</pre>';
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a href='$authUrl'>Connect Me!</a>";
}
?>
From above code My authentication works fine and i am able to get the Token.But This code allows access for Google Plus .I need To authenticat Blogger with Oauth.Google documentation did not help me.Can some one please guide me .Thanks.

PHP Google API - Missing scope

I'm using the following, based on Google's calendar sample app which worked fine.
$client = new \Google_Client();
$client->setApplicationName("Google Calendar PHP Starter Application");
$client->setClientId('myclientid.apps.googleusercontent.com');
$client->setClientSecret('mysecret');
$client->setRedirectUri('http://localhost/admin/index.php?m=1&e=calendar');
$client->setDeveloperKey('mykey');
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if (!$client->getAccessToken()) {
$authUrl = $client->createAuthUrl();
header('Location: ' . $authUrl);
}
But I'm getting:
Error: invalid_request
Missing required parameter: scope
Was missing this line after I set the developerKey
$cal = new \Google_CalendarService($client);
I guess the act of getting a calendar service from the client sets the scope. Pretty reasonable.

Categories