This is driving me mental.
I have a web application and an associated Google Account. I want the web application to use this Google drive and this google drive ONLY...PERMANENTLY.
I am using google/apiclient:^2.0
I have set up a OAuth 2.0 client ID and downloaded the JSON file.
I have this:
$this->client = new \Google_Client();
$this->client->setClientId('blahblahblah.apps.googleusercontent.com');
$this->client->setAuthConfig(base_path() . '/resources/assets/client_secret.json');
$this->client->setApplicationName('My Web App');
$this->client->setRedirectUri('somewhere');
$this->client->setScopes('https://www.googleapis.com/auth/drive');
return $this->client;
Now when I run...
$authUrl = $this->client->createAuthUrl();
echo 'Go';
And authenticate I get a Code...
Now my question is...what do I do with that code?
I've tried...$this->client->authenticate('code here');
and also $accessToken = $client->fetchAccessTokenWithAuthCode('code here);
I keep getting either dailyLimitExceededUnreg or Invalid token format
I'm really confused and frustrated with the Google authentication API and the docs seem way out of date.
Any hints in the right direction would be amazing.
Thanks
I did something like this a couple of years ago and also had some difficulties with the documentation.
I went through the code to find it for you. I used this for Gmail contact list but the procedure looks the same. I'll try to explain the process I went through and I think it should help you out.
This it the part where you are. You get the code Google send you and just save it in a Session Variable
if (isset($_GET['code'])) {
$auth_code = $_GET["code"];
$_SESSION['google_code'] = $auth_code;
}
Now you will have to post to oauth2 to authenticate and get your acesstoken
$auth_code = $_SESSION['google_code'];
$max_results = 300;
$fields=array(
'code'=> urlencode($auth_code),
'client_id'=> urlencode($google_client_id),
'client_secret'=> urlencode($google_client_secret),
'redirect_uri'=> urlencode($google_redirect_uri),
'grant_type'=> urlencode('authorization_code')
);
$post = '';
foreach($fields as $key=>$value)
{
$post .= $key.'='.$value.'&';
}
$post = rtrim($post,'&');
$result = curl('https://accounts.google.com/o/oauth2/token',$post);
$response = json_decode($result);
$accesstoken = $response->access_token;
With the token you'll be able to curl Google Drive's endpoint and get your results
$url = 'https://www.google.com/m8/feeds/contacts/default/full?max-results='.$max_results.'&alt=json&v=3.0&oauth_token='.$accesstoken;
$xmlresponse = curl($url);
To get the access token you need the following in you "somewhere" route:
$client->authenticate($_GET['code']);
$access_token = $client->getAccessToken();
the access token is used to log you into your google drive
to work with google drive you need to instantiate Google_Service_Drive
$drive = new Google_Service_Drive($client);
$files = $drive->files->listFiles(array())->getItems();
Note: access tokens are a form of user+password that expire over time so you need to fetch new ones if they expire
Related
On
YouTube API to fetch all videos on a channel
found compact sample PHP under heading "Here is the code that will return all video ids under your channel".
Program shown below.
I expanded the program to fetch various attributes of each video, including ACCESS.
I have a channel with over 20,000 videos and large quote.
The program ran nicely and produced a .csv with video attributes.
It ran for about 2 hours and 10 minutes and stopped at 20,000 videos. In addition it only picked up PUBLIC videos.
How can the above two issues be remedied?
<?php
// FROM https://stackoverflow.com/questions/18953499/youtube-api-to-fetch-all-videos-on-a-channel/70071113#70071113
$baseUrl = 'https://www.googleapis.com/youtube/v3/';
// https://developers.google.com/youtube/v3/getting-started
$apiKey = 'API_KEY';
// If you don't know the channel ID see below
$channelId = 'CHANNEL_ID';
$params = [
'id'=> $channelId,
'part'=> 'contentDetails',
'key'=> $apiKey
];
$url = $baseUrl . 'channels?' . http_build_query($params);
$json = json_decode(file_get_contents($url), true);
$playlist = $json['items'][0]['contentDetails']['relatedPlaylists']['uploads'];
$params = [
'part'=> 'snippet',
'playlistId' => $playlist,
'maxResults'=> '50',
'key'=> $apiKey
];
$url = $baseUrl . 'playlistItems?' . http_build_query($params);
$json = json_decode(file_get_contents($url), true);
$videos = [];
foreach($json['items'] as $video)
$videos[] = $video['snippet']['resourceId']['videoId'];
while(isset($json['nextPageToken'])){
$nextUrl = $url . '&pageToken=' . $json['nextPageToken'];
$json = json_decode(file_get_contents($nextUrl), true);
foreach($json['items'] as $video)
$videos[] = $video['snippet']['resourceId']['videoId'];
}
print_r($videos);
?>
In addition it only picked up PUBLIC videos.
The code you are currently using uses an API key. API keys are used to access public data only.
If you want to access private data then you will need to be authorized using Oauth2 as a user who has access to the private videos.
It ran for about 2 hours and 10 minutes and stopped at 20,000 videos.
This question is a little harder for me to answer as i cant test it i don't have a YouTube Channel with 20k videos.
I can guess that as you are using an api key there is a limit to the number of videos they will let you download with an api key. They probably dont want people downloading all public videos on YouTube.
I suggest that you try and authorize it with Oauth2 and see if the limit is still there.
php example with Oauth2.
Create installed app credentials see video
make sure to enable the YouTube data api under libary.
change the channelId in this code to your own
Code
<?php
/**
* Sample PHP code for youtube.search.list
* See instructions for running these code samples locally:
* https://developers.google.com/explorer-help/guides/code_samples#php
*/
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
throw new Exception(sprintf('Please run "composer require google/apiclient:~2.0" in "%s"', __DIR__));
}
require_once __DIR__ . '/vendor/autoload.php';
$client = new Google_Client();
$client->setApplicationName('API code samples');
$client->setScopes([
'https://www.googleapis.com/auth/youtube.force-ssl',
]);
// TODO: For this request to work, you must replace
// "YOUR_CLIENT_SECRET_FILE.json" with a pointer to your
// client_secret.json file. For more information, see
// https://cloud.google.com/iam/docs/creating-managing-service-account-keys
$client->setAuthConfig('YOUR_CLIENT_SECRET_FILE.json');
$client->setAccessType('offline');
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open this link in your browser:\n%s\n", $authUrl);
print('Enter verification code: ');
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Define service object for making API requests.
$service = new Google_Service_YouTube($client);
$queryParams = [
'channelId' => 'UCyqzvMN8newXIxyYIkFzPvA',
'forMine' => false
];
$response = $service->search->listSearch('snippet', $queryParams);
print_r($response);
Note: I dont have php installed on this machine so i cant test it but this should be close. Let me know if you have any issues.
I am working on an app that reads and updates values in a Google Spreadsheet using Google Sheets API. I am able to read using my developer key, however attempting to write returns this error:
"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential."
Read (works fine):
$client = new Google_Client();
$client->setApplicationName("XXX");
$client->setDeveloperKey("XXX");
$service = new Google_Service_Sheets($client);
$spreadsheetId = "XXX";
$range = 'promocodes';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
Write code (error):
$client = new Google_Client();
$client->setApplicationName("XXX");
$client->setDeveloperKey("XXX");
$service = new Google_Service_Sheets($client);
$spreadsheetId = "XXX";
$range = 'promocodes!C4';
$values = [1];
$body = new Google_Service_Sheets_ValueRange([
'values' => $values
]);
$params = [
'valueInputOption' => $valueInputOption
];
$result = $service->spreadsheets_values->update($spreadsheetId, $range,
$body, $params);
printf("Cells updated.", $result->getUpdatedCells());
As I understand it, the Google API will allow you to read without an access token (using a developer key for credentials) however you can not update or add information without an oauth2 authentication method which involves sending credentials to google, receiving back a code from them, using that code to get an access token, then using that access token as your credentials to add or update information.
I had a small problem in using twitter oauth in order to get some user data.
// TWITTER APP KEYS
$consumer_key = 'some data';
$consumer_secret = 'some data';
// GETTING ALL THE TOKEN NEEDED
$oauth_verifier = $_GET['oauth_verifier'];
$token_secret = $_COOKIE['token_secret'];
$oauth_token = $_COOKIE['oauth_token'];
// EXCHANGING THE TOKENS FOR OAUTH TOKEN AND TOKEN SECRET
$connection = new TwitterOAuth($consumer_key, $consumer_secret, $oauth_token, $token_secret);
$access_token = $connection->oauth("oauth/access_token", array(
"oauth_verifier" => $oauth_verifier
));
$accessToken = $access_token['oauth_token'];
$secretToken = $access_token['oauth_token_secret'];
$connection = new TwitterOAuth($consumer_key, $consumer_secret, $accessToken, $secretToken);
$connection->get("users/search");
$content = $connection->get("account/verify_credentials");
$media1 = $connection->upload('media/upload', [
'media' => $this->session->image['generatedAbs']
]);
$parameters = [
'media_id' => implode(',', [
$media1->media_id_string
])
];
$result = $connection->post('account/update_profile_banner', $parameters);
now I want to retrieve some information like the name and last name of the connected user , his profile picture link , email adress and his location if it's possible
I read the official twitter dev documentation and i didn't find a way how to use it in my method , i tried to debug my controller using this way
$connection = new TwitterOAuth($consumer_key, $consumer_secret, $accessToken, $secretToken);
$connection->get("https://api.twitter.com/1.1/users/profile_banner.json?screen_name=twitterapi");
$result = json_decode($connection);
// debug the returned result
Zend_Debug::dump($result,$label="debug gass" , $echo= true);
So to retrieving information from twitter using php and Twitter Oauth is super easy , just allow me to enumerate the steps
1) Getting an oauth_token and oauth_verifier (steps are clearly explained in the question
2) The funny part is now :D , you need to copy paste the following in the controller of you callback page:
$connection = new TwitterOAuth($consumer_key, $consumer_secret, $accessToken, $secretToken);
$content = $connection->get("account/verify_credentials");
Now you really have finished everything , just debug the result :D
Zend_Debug::dump($content->profile_image_url , $label = "achref gassoumi", $echo = true);
ps: i used zend debugger since i'm working , if you are working with other framework or with pure php just echo the following result for example :
echo $credentials->screen_name;
echo $credentials->profile_image_url ;
echo $credentials->location;
echo $credentials->profile_background_image_url;
To retrieve other information you might need please visit the official twitter Oauth documentation of GET account/verify_credentials.
Im really struggling w/ the OAuth for Khan Academy. This is for my class website (Im a teacher) and I want to pull in user data on particular students. If I could do the OAUTH I would be fine. Im using PHP.
There seems to be many librarys out there, I have been playing w/ Google Oauth (located here http://code.google.com/p/oauth-php/source/browse/trunk/example/client/twolegged.php)
I can formulate the token request fine, although when I call it in the script, it seems like it tries to redirect to another page and gets blocked there.
http://myonlinegrades.com/prealg/khan/oauth-php/example/client/twoleggedtest.php
Im really struggling - Id love any help you might offer.
Code below:
<?php
include_once "../../library/OAuthStore.php";
include_once "../../library/OAuthRequester.php";
// Test of the OAuthStore2Leg
// uses http://term.ie/oauth/example/
$key = '*********';//'<your app's API key>';
$secret = '***********';//'<your app's secret>';
$callBack = "http://myonlinegrades.com/prealg/test2.php5";
$url = 'http://www.khanacademy.org/api/auth/request_token';
$options = array('consumer_key' => $key, 'consumer_secret' => $secret);
OAuthStore::instance("2Leg", $options);
$method = "GET";
//$params = null;
$params = array(oauth_consumer_key => $key,oauth_callback=>$callBack);
try
{
// Obtain a request object for the request we want to make
$request = new OAuthRequester($url, $method, $params);
// Sign the request, perform a curl request and return the results,
// throws OAuthException2 exception on an error
// $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string)
$result = $request->doRequest();
$response = $result['body'];
if ($response != 'oauth_token=requestkey&oauth_token_secret=requestsecret')
{
echo 'Error! $response ' . $response;
}
else
{
}
var_dump($response);
}
catch(OAuthException2 $e)
{
echo "Exception" . $e->getMessage();
}
?>
Not sure this is what you're looking for, but I put together a simple example of doing oAuth with Khan Academy using the Temboo SDK: take a look at https://github.com/matthewflaming/temboo-experiments/tree/master/KhanAcademyOauth
(Full disclosure: I work at Temboo)
I am creating an API request (GET bucket) for the storage API and one of the required parameter is the "Authorization" header.
Please note that I am using a Service Account to access the API.
I followed the document https://developers.google.com/accounts/docs/OAuth2ServiceAccount to get the access token for the "Authorization" header so I could send an authorized request to their REST API. The problem is I am always getting the "invalid_grant" error.
Use this code to check it out:
<?php
error_reporting(E_ERROR);
const CLIENT_ID = 'XXXXXXXXXXXX.apps.googleusercontent.com';
const SERVICE_ACCOUNT = 'XXXXXXXXXXXX#developer.gserviceaccount.com';
const KEY_FILE = 'XXX.p12';
function get_oauth_access_token()
{
$header[alg] = 'RS256';
$header[typ] = 'JWT';
$header = urlencode(base64_encode(utf8_encode(json_encode($header))));
$assertion_time = time();
$claim[iss] = CLIENT_ID; //also tried SERVICE_ACCOUNT here, no improvement
$claim[scope] = 'https://www.googleapis.com/auth/devstorage.read_only';
$claim[aud] = 'https://accounts.google.com/o/oauth2/token';
$claim[exp] = $assertion_time + 3600;
$claim[iat] = $assertion_time;
$claim = urlencode(base64_encode(utf8_encode(json_encode($claim))));
$data = $header . '.' . $claim;
$p12 = file_get_contents(KEY_FILE);
$cert = array();
openssl_pkcs12_read($p12, $cert, 'notasecret');
$priv_key_id = openssl_get_privatekey($cert[pkey]);
openssl_sign($data, $signature, $priv_key_id, 'sha256');
$signature = urlencode(base64_encode($signature));
$assertion = $data . '.' . $signature;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://accounts.google.com/o/oauth2/token');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('grant_type'=>'assertion',
'assertion_type'=>'http://oauth.net/grant_type/jwt/1.0/bearer',
'assertion'=>$assertion));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
var_dump($result);
var_dump($error);
}
get_oauth_access_token();
Is there anything wrong in this code that causes the "invalid_grant" error?
Your problem might be the time of your server.
I faced a problem with Google Analytics: all my code was correct but the time of my server was some seconds in the future compared with Google's time. You can delay your server's time a few minutes to do a test.
If it works you can use NTP for example, to keep the server clock correct.
Here's a simple PHP program illustrating use of a service account with the Google Cloud Storage RESTful HTTP interface. I've tested this code with a service account and it seems to work fine. Let me know if you have any further questions.
<?php
require_once 'apiClient.php';
// Define constants.
const CLIENT_ID = 'YOUR_CLIENT_ID_GOES_HERE';
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME_GOES_HERE';
const KEY_FILE = 'key.p12';
const BUCKET = 'marc-us';
// Obtain OAuth 2.0 access token for service account.
$client = new apiClient();
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new apiAssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/devstorage.full_control'),
$key)
);
$client::$auth->refreshTokenWithAssertion();
$json = $client->getAccessToken();
$accessToken = json_decode($json)->access_token;
// Add access token to Authorization header of HTTP request.
$ch = curl_init('http://commondatastorage.googleapis.com/' . BUCKET);
curl_setopt($ch, CURLOPT_HTTPHEADER,
array('Authorization: OAuth ' . $accessToken));
$resp = curl_exec($ch);
curl_close($ch);
// Display results.
print '<h2>Response:</h2><pre>' . $resp . '</pre>';
?>
The code in my last response works fine for me so I suspect you're facing an environmental problem. At any rate, I consulted with the owner of the Google PHP client library and he provided a better way to refresh the access token without resorting to calls to the internal refreshTokenWithAssertion() method. He suggested this technique:
$req = new apiHttpRequest(YOUR_URL);
$val = $client->getIo()->authenticatedRequest($req);
The call to authenticatedRequest() takes care of refreshing the access token (with assertion credentials if they're set) as needed. I modified the code above to use this approach and it works fine for me. Note that both the old and new versions work for me so there's no functional difference but I think the new version is better because it avoids the internal call, uses the Google PHP client lib instead of curl to execute the request and results in much shorter, simpler code.
<?php
require_once 'apiClient.php';
// Define constants.
const SERVICE_ACCOUNT_NAME = 'YOUR_SERVICE_ACCOUNT_NAME';
const KEY_FILE = 'key.p12';
const BUCKET = 'marc-us';
// Obtain service account credentials assertion.
$client = new apiClient();
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new apiAssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/devstorage.full_control'),
$key)
);
// Create HTTP request, authorize and execute.
$req = new apiHttpRequest('http://commondatastorage.googleapis.com/' . BUCKET);
$resp = $client::getIo()->authenticatedRequest($req);
// Display results.
print '<h2>Response:</h2>' . $resp->getResponseBody();
?>
I had the same error, but with Java. My problem was that the time in seconds to exp and iat was in GMT-5 and the API google Auth is in GMT. Then I changed the time to GMT value and all is OK.