Unable to get the refresh_token from google Oauth response - php

I am new to google client auth. I am trying to upload a file to my google drive using this php google client downloaded from here https://github.com/google/google-api-php-client
public function oauth2callback(){
set_include_path(get_include_path() . PATH_SEPARATOR . ROOT .DS. "vendors");
require_once 'Google/Client.php';
$client = new Google_Client();
$client->setClientId('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
$client->setClientSecret('xxxxxxxxxxxxxxxxx');
$client->setRedirectUri('http://example.com/auth/oauth2callback');
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
$client->setState('offline');
$authUrl = $client->createAuthUrl();
if (isset($_GET['code'])) {
$authCode = trim($_GET['code']);
$accessToken = $client->authenticate($authCode);
print_r($accessToken);
$client->setAccessToken($accessToken);
}
if ($client->getAccessToken()) {
// To do
}else{
$authUrl = $client->createAuthUrl();
echo "<a href='$authUrl'>Login Now</a>";
}
}
In the response, i only recieve this
{"access_token":"ya29.eQAeXvi4c5CAGRwAAAAKr55Tljr6z_GpdfjyY0xbrD15XGikNRL-D724Hx1L_g","token_type":"Bearer","expires_in":3600,"created":1410085058}
without any refresh token.
I just want to get the refresh token from the response for later use.
I also followed this question
Set the state to offline, revoked all the previous access that belonged to this app,
even tried with fresh new account/apps.. but never received refresh token..
Please guys help me out...

I was missing the access_type=offline..
So, adding
$client->setAccessType('offline');
fixed the problem.

Related

Composer and Google Auth JSON Key

I need a sample code that shows me how I use the .json file I got from Google to authenticate that I am the owner of the storage Bucket.
Basically users upload their profile picture and I want to store it using Google Cloud, but every time I run the code below it says
Could not load the default credentials
I have gone to the URL it gives and I get a 404 error.
My index file has this in it
<?php
require 'vendor/autoload.php';
require 'sys/v1/core.php';
require 'sys/v1/google_cloud_storeage_upload.php';
$client = new Google_Client();
$client->setAuthConfig('/home/SITE/FOLDER/KEY-GOOGLE.json');
// $service implements the client interface, has to be set before auth call
$service = new Google_AnalyticsService($client);
if (isset($_GET['logout'])) { // logout: destroy token
unset($_SESSION['token']);
die('Logged out.');
}
if (isset($_GET['code'])) { // we received the positive auth callback, get the token and store it in session
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) { // extract token from session and configure client
$token = $_SESSION['token'];
$client->setAccessToken($token);
}
if (!$client->getAccessToken()) { // auth call to google
$authUrl = $client->createAuthUrl();
header("Location: ".$authUrl);
die;
}
?>

Youtube API v3 without the need of End-User Authentication

Im trying to create a Youtube upload script that does not require the end user to login in order to upload a video to my channel. The issue is I can gain the access token but it expires after an hour of being inactive.
Also I am unsure where you can get the "refresh_token" from.
So essentially I wish to have this Google API v3 script not require any client side authentication in order to upload video's.
From what I gather from the API documentation at google if I had the "refresh_token" I could renew the token without the need of user interaction required.
Please see below my existing code on the matter.
<?php
$key = json_decode(file_get_contents('the_key.txt'));
require_once 'Client.php';
require_once 'Service/YouTube.php';
session_start();
$OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID.apps.googleusercontent.com';
$OAUTH2_CLIENT_SECRET = 'YOUR_SECRET_KEY';
$REDIRECT = 'http://example.com/test.php';//Must be exact as setup on google API console
$APPNAME = "Test upload app";
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$client->setRedirectUri($REDIRECT);
$client->setApplicationName($APPNAME);
$client->setAccessType('offline');
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
}
if (isset($_SESSION['token'])) {
//if session current save to file updates token key
$client->setAccessToken($_SESSION['token']);
echo '<code>' . $_SESSION['token'] . '</code><br>';
file_put_contents('the_key.txt', $_SESSION['token']);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
if($client->isAccessTokenExpired()) {
echo "Token Expired<br>Attempt Refresh: ";
$client->refreshToken($key->access_token);
//refresh token, now need to update it in session
$_SESSION['access_token']= $client->getAccessToken();
}
$_SESSION['token'] = $client->getAccessToken();
///////////////////////////////////////////////////////////////////////
//Run Upload script here from google Youtube API v3
//https://developers.google.com/youtube/v3/code_samples/php#resumable_uploads
///////////////////////////////////////////////////////////////////////
} else {
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = '<h3>Authorization Required</h3><p>You need to authorise access before proceeding.<p>';
}
?>
<!doctype html>
<html>
<head>
<title>My Uploads</title>
</head>
<body>
<?php echo $htmlBody?>
</body>
</html>
If someone can look over this code and tell me what I'm missing would be great.
I finally figured it out!!!
Thanks to Burcu Dogan for the solution:
Automatically refresh token using google drive api with php script
It turns out that the refresh_token will only be returned on the first $client->authenticate(), for that account you login with and you need to permanently store it remove the need for the user authentication.
As I had already authenticated desired user I was unable to regenerate the refresh_token with this project so I had to delete the project and recreate it.
Re-Authenticate the user and the refresh_token appeared! I then stored this token safe and have not had any issues since.
If you do not wish to delete your project and start again you can also go to oAuth Playground and aquire your refresh_token that way.
YouTube run through
Hope this help solve a lot of peoples problems online.

Google API and OAuth 2.0

I'm trying to use google calendar API with php library and i'm facing issues on the authentification of the user to the google api.
I have a question. I've seen some come where you had to set the Api key / developer key to the Google_Client object with the method setDeveloperKey(), but i've also seen some people who don't. Could someone explain to me what difference does it make ?
The thing i'd like to do is to connect a user who have a google account to my application so he can add, list, remove, etc, events from a calendar. This is what i'm doing for the moment for the authentification :
$client = new Google_Client();
$client->setApplicationName("Test GCAL");
$client->setClientId($clientid);
$client->setClientSecret($clientsecret);
$client->setRedirectUri($callback_url);
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
$client->setScopes("https://www.googleapis.com/auth/calendar");
$service = new Google_Service_Calendar($client);
Am i doing it right ?
Does someone have a working commented code that i can analyse ? I can't find one that's working on the internet.. Or maybe a tutorial that explain everything about google api and oauth stuff. I'm so confused about tokens and nobody seems to use refresh tokens, and to me that's essential.. But maybe i'm wrong ?
Thanks for your answers
I don't think you NEED to use setDeveloperKey I suspect that its only used for public APIs to enable you to use them but I haven't really tested it or thought about it before. I will have to look into that a bit more.
This is the code I use for connecting to Google Calendar with Oauth2. ripped directly from the Accessing Google Calendar with PHP – Oauth2 tutorial
<?php
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
require_once 'CalendarHelper.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/calendar.readonly'));
//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_Calendar($client);
$calendarList = $service->calendarList->listCalendarList();;
print_r($calendarList);
while(true) {
foreach ($calendarList->getItems() as $calendarListEntry) {
echo $calendarListEntry->getSummary()."<br>\n";
}
$pageToken = $calendarList->getNextPageToken();
if ($pageToken) {
$optParams = array('pageToken' => $pageToken);
$calendarList = $service->calendarList->listCalendarList($optParams);
} else {
break;
}
}
}
?>

Unable to refresh OAuth2 token in PHP, invalid grant

I need to make a PHP script that creates a sigle event on Google Calendar.
I had no problems setting up client id, client secret, dev key and creating a new event.
My only problem is with OAuth2, in particular I need to make a permanent connection and I do not want to do the authentication everytime I run the script.
Actually, with this script I'm able to get a token and a refresh token, but every hour my token expires and I don't know how to refresh it. How can I edit this code to do that?
Can I save both the token and the refresh token somewhere and always use the same data?
I obtain an uncaught exception 'Google_AuthException' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant"
I have already read some other posts about this topic here in stackoverflow but I still haven't found a solution... :\
<?php
require_once 'src/Google_Client.php';
require_once 'src/contrib/Google_CalendarService.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("Calendar App");
$client->setClientId('xxxx');
$client->setClientSecret('yyy');
$client->setRedirectUri('http://www.zzzzzz');
$client->setDeveloperKey('kkk');
$client->setAccessType('offline');
$cal = new Google_CalendarService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
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'])) {
//echo $_SESSION['token'];
//$client->setAccessToken($_SESSION['token']);
$authObj = json_decode($_SESSION['token']);
$accessToken = $authObj->access_token;
$refreshToken = $authObj->refresh_token;
$tokenType = $authObj->token_type;
$expiresIn = $authObj->expires_in;
echo 'access_token = ' . $accessToken;
echo '<br />';
echo 'refresh_token = ' . $refreshToken;
echo '<br />';
echo 'token_type = ' . $tokenType;
echo '<br />';
echo 'expires_in = ' . $expiresIn;
}
if(!empty($cookie)){
$client->refreshToken($this->Cookie->read('token'));
}
if ($client->getAccessToken()) {
$calList = $cal->calendarList->listCalendarList();
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
// Creation of a single event
$event = new Google_Event();
$event->setSummary($event_name);
$event->setLocation('');
....
?>
Thanks a lot for your support!
This page https://developers.google.com/accounts/docs/OAuth2WebServer#offline explains how the refresh token works, and how to use it to get a fresh access token using raw http.
From this question How to refresh token with Google API client? here is the php equivalent
here is the snippet to set token, before that make sure the access type should be set to offline
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['access_token'] = $client->getAccessToken();
}
To refresh token
$google_token= json_decode($_SESSION['access_token']);
$client->refreshToken($google_token->refresh_token);
this will refresh your token, you have to update it in session for that you can do
$_SESSION['access_token']= $client->getAccessToken()
DEBUGGING
Follow these three steps to debug any oauth application
Make sure you have read https://developers.google.com/accounts/docs/OAuth2 and also the appropriate sub-page (webapp, javascript, etc) depending on which flavour of oauth you are using. You won't get very far debugging your app if you don't understand what it's doing.
Use the Oauth Playground at https://developers.google.com/oauthplayground/ to walk through the Oauth steps and ultimately make a Google API call. This will confirm your understanding and show you what the http calls and responses look like
Use tracing/logging/proxy etc to trace the actual http traffic from your app. Compare this with what you observed in step 2. This should show you where the problem lies.
I got this error before because I was trying to authenticate twice.
Since you have this line:
if (isset($_GET['code']))
It will try to authenticate when the code is in the query string regardless of whether you're already authenticated. Try checking whether the SESSION token is present before trying to (re)authenticate.
Try removing setDeveloperKey(), this was causing some issues for me and it seems unneeded.

Insert Moment in Google+ using Google PHP Client

I'm trying to insert some activity app in a Google+ profile as shown in this documentation page:
https://developers.google.com/+/api/latest/moments/insert
I successfully obtain the access token needed, but seems the moments->insert method doesn't make anything.
If successful I would expect to see something on this page, once made the access, but nothing happen
https://plus.google.com/u/0/apps/activities
That's my code
<?php
require_once '../google-api-php-client/Google_Client.php';
require_once '../google-api-php-client/contrib/Google_PlusService.php';
session_start();
$client = new Google_Client();
$client->setClientId('xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com');
$client->setClientSecret('xxxxxxxxxxxxxxxxxxxxxxxx');
$client->setRedirectUri('http://www.myregisteredcallbackurl.com');
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/plus.login'));
$client->setApprovalPrompt('force');
$plus = new Google_PlusService($client);
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
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'])) {
echo 'Logout<br><br>'.PHP_EOL.PHP_EOL;
$client->setAccessToken($_SESSION['token']);
$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);
}
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
} else {
$authUrl = $client->createAuthUrl();
echo 'Connect<br>';
}
You need to add the requestvisibleactions permissions to your scope. The easiest way to do this is to switch from the conventional OAuth 2.0 flow to the new Google+ Sign-In flow - the Google+ team provides a PHP sample for Google+ Sign-In. If you want to continue using the older OAuth flow, you need to append request_visible_actions=[the app activity types] to your authorization URL.
Related questions:
Google+ PHP moments not working
Google+ Insert moment using dot-net-client
Google+ unable to insert moment
In your code, you are really close, the following seems to work for me:
$client = new Google_Client();
$client->setClientId('YOUR_CLIENT_ID');
$client->setClientSecret('YOUR_CLIENT_SECRET');
$client->setRedirectUri('http://example.com/callback.php');
$client->setAccessType('offline');
$client->setScopes(array('https://www.googleapis.com/auth/plus.login'));
$client->setRequestVisibleActions(array('https://schemas.google.com/AddActivity'));
$plus = new Google_PlusService($client);
To check the app activities that you have written, visit the app activity log.

Categories