I want to upload files to Google Drive using the API, but I need to do this using a cron job (autobackup of webfiles+sql to Google drive).
That means (I suppose) that I need to authenticate using something else than the user interaction method.
The example that I have been using: https://developers.google.com/api-client-library/php/auth/web-app to get me going, and its working with user authenticating.
I would appreciate some tips on how to do this without user interaction, so it can run on a cronjob.
Here are the PHP code for authenticate and upload file (working example with manual user auth and single file upload)
<?php
require_once 'google-api-php-client/vendor/autoload.php';
/* Config */
$servername = 'content here';
$redirect_uri = 'https://example.com/';
$client = new Google_Client();
$client->setAuthConfig('client_manual_authentiation.json');
$client->addScope(Google_Service_Drive::DRIVE);
if(isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive = new Google_Service_Drive($client);
foreach($drive->files->listFiles(array("q" => "name = '{$servername}'"))->getFiles() as $key => $element){
if($element->name == $servername){
//create todays folder on Google Drive
$today_folder_meta = new Google_Service_Drive_DriveFile(array(
'name' => 'myfile.txt',
'mimeType' => 'application/vnd.google-apps.folder',
'parents' => array($element['id'])
));
$today_folder = $drive->files->create($today_folder_meta, array(
'fields' => 'id'
));
}
}
}else{
if (!isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
}
?>
To do this, you want to create a Google OAuth2 Service Account. You can then download a set of JSON credentials that your app will use to authenticate without user interaction.
This is described in the following article:
Using OAuth 2.0 for Server to Server Applications
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
You will then be able to download credentials like the following to use in your app:
{
"type":"service_account",
"project_id":"your-project-id",
"private_key_id":"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
"private_key":"-----BEGIN PRIVATE KEY-----\nMIIEv...4XIk=\n-----END PRIVATE KEY-----\n",
"client_email":"foobar#bazqux.iam.gserviceaccount.com",
"client_id":"12345678901234567890",
"auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/foobar%40bazqux.iam.gserviceaccount.com"
}
Here is a Google PHP example of how to use this:
https://github.com/google/google-api-php-client/blob/master/examples/service-account.php
You can create the Service Account in the Google API Console as shown here:
Related
I've been following a series of tutorials, and my PHP page hosted on XAMPP is able to upload a file to Google Drive using OAuth for authentication. However, I've realised that the application uploads the file to the Drive of whichever user logs in at the OAuth screen. For my project I need the files to always go to the same Drive regardless of who has logged in.
Below is the code for the page.
<?php
require __DIR__ . '/../vendor/autoload.php';
$client = new Google_Client();
// Get your credentials from the console
$client->setClientId('<<CLIENT ID>>');
$client->setClientSecret('<<CLIENT SECRET>>');
$client->setRedirectUri('https://127.0.0.1/Transcode/controller/processInput.php');
$client->setScopes(array('https://www.googleapis.com/auth/drive.file'));
session_start();
if (isset($_GET['code']) || (isset($_SESSION['access_token']) && $_SESSION['access_token'])) {
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
} else
$client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Drive($client);
//Insert a file
$file = new Google_Service_Drive_DriveFile();
$file->setName(uniqid().'.mkv');
$file->setDescription('A test document');
$file->setMimeType('application/octet-stream');
$data = file_get_contents('../110mb.mkv');
$createdFile = $service->files->create($file, array(
'data' => $data,
'mimeType' => 'application/octet-stream',
'uploadType' => 'multipart'
));
print_r($createdFile);
} else {
$authUrl = $client->createAuthUrl();
header('Location: ' . $authUrl);
exit();
}
?>
I've previously attempted to set this up using a Service Account instead of via OAuth, although I was unable to find examples of how to set this up that I could follow, as I am a beginner as far as the Google APIs are involved.
Essentially, what I'm looking for is a way to force the page to always upload to the same Drive. If this would better be implemented using a Service Account, then examples and links to tutorials would be appreciated.
Down you can see my code and it uploads files to my google drive. Now I am trying to use service account to let the people to upload files to my Google drive without their google accounts (Visitors will submit html form with their file and my app will upload that file to my drive ). But I am stuck with it. Can not find even just one working example. Any ideas?
$client = new Google\Client();
$client->setAuthConfig('credentials.json');
$client->addScope(Google\Service\Drive::DRIVE);
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$client->setRedirectUri($redirect_uri);
if (isset($_GET['code'])) {
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
$client->setAccessToken($token);
// store in the session also
$_SESSION['upload_token'] = $token;
// redirect back to the example
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
if (!empty($_SESSION['upload_token'])) {
$client->setAccessToken($_SESSION['upload_token']);
if ($client->isAccessTokenExpired()) {
unset($_SESSION['upload_token']);
}
} else {
$authUrl = $client->createAuthUrl();
}
echo $client->getAccessToken();
if ($_SERVER['REQUEST_METHOD'] == 'GET' && $client->getAccessToken()) {
// We'll setup an empty 1MB file to upload.
DEFINE("TESTFILE", 'test.jpg');
if (!file_exists(TESTFILE)) {
$fh = fopen(TESTFILE, 'w');
fseek($fh, 1024 * 1024);
fwrite($fh, "!", 1);
fclose($fh);
}
// This is uploading a file directly, with no metadata associated.
$file = new Google\Service\Drive\DriveFile();
$service = new Google_Service_Drive($client);
$file->setName("Hello World!");
$result = $service->files->create(
$file,
[
'data' => file_get_contents(TESTFILE),
'mimeType' => 'application/octet-stream',
'uploadType' => 'media'
]
);
$permissionService = new Google_Service_Drive_Permission();
$permissionService->role = "reader";
$permissionService->type = "anyone"; // anyone with the link can view the file
$service->permissions->create($result->id, $permissionService);
The following code will show you how to set up service account authorization.
Remember though the files will be uploaded to the service accounts drive account. If you want them uploaded to your personal drive account. You need to share a directory on your drive account with the service account. You do that though the web app like you would any other user, using the service account email address. Its the property that looks like an email.
You should just be able to remove the auth you have now and then use this. You will however need set the parents in the upload metadata to be that of that directory you want the fill uploaded to.
// Load the Google API PHP Client Library.
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
* Gets the Google client refreshing auth if needed.
* Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
* Initializes a client object.
* #return A google client object.
*/
function getGoogleClient() {
return getServiceAccountClient();
}
/**
* Builds the Google client object.
* Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
* Scopes will need to be changed depending upon the API's being accessed.
* array(Google_Service_Analytics::DRIVE)
* List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
* #return A google client object.
*/
function getServiceAccountClient() {
try {
// Create and configure a new client object.
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(array(Google_Service_Analytics::DRIVE));
return $client;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Doing something like this will then get you the same service object.
$service = new Google_Service_Drive(getGoogleClient());
I'm here with a little problem to connect my script with a Google Drive API using a credentials json file.
This is my code:
$oauth_credentials = __DIR__.'\credentials.json';
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$client = new Google\Client();
$client->setAccessType('offline');
$client->setAuthConfig($oauth_credentials);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
if (isset($_GET['code'])) {
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
var_dump($token);
}
Obviously I used composer to add google apiclient project to my script, and I used the cloud console of google to enable Drive API and create the credentials for this, and I used the credentials.json file downloaded of Google Console.
All is apparently good, I added a test account and used this account to accept permissions to use the Drive API.
Using the playground, in this URL https://developers.google.com/oauthplayground I test my credentials and I get the authorization code to create a refresh token and access token, but when i use this authorization code in my script the result is this: ""
'error' => string 'invalid_grant' (length=13)
'error_description' => string 'Bad Request' (length=11)
Any suggests? this code is exactly like the code appear in the Google examples.
My problem is that the focus is wrong way, I create a service account and generate the json credentials file and I use this code for upload a file:
putenv('GOOGLE_APPLICATION_CREDENTIALS=credentials.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/drive.file']);
try {
$service = new Google_Service_Drive($client);
$file_path = 'example.txt';
$file = new Google_Service_Drive_DriveFile();
$file->setName('example.txt');
$file->setParents([$this->folder_id]);
$file->setDescription('Example description text');
$result = $service->files->create($file,[
'data' => file_get_contents($file_path),
'mimeType' => 'text/plain',
'uploadType' => 'text'
]);
echo 'Link to the uploaded file';
}
catch(Google_Service_Exception $gs)
{
$m = json_decode($gs->getMessage());
echo $m->error->message;
}
catch(Exception $e)
{
echo $e->getMessage();
}
I’m trying to add an Azure Active Directory OAuth 2.0 login to my PHP web app.
I’m using TheNetworg provider for Azure based on the PHP League’s OAuth 2.0 Client.
It seems to work correctly, in that I get an Access Token returned.
However, the token is meant to look like a JSON Web Token, but it doesn’t – don’t know what the token is is to be honest.
Here's the code I use: -
<?php
require "..\\vendor\\autoload.php";
session_start();
$client_id = 'aloadofnumbersandletters';
$client_secret = 'aloadofnumbersandletters';
$redirect_uri = 'http://localhost:54680/VirtualWebServer/logi03.php';
$provider = new TheNetworg\OAuth2\Client\Provider\Azure([
'clientId' => $client_id,
'clientSecret' => $client_secret,
'redirectUri' => $redirect_uri]);
$provider->defaultEndPointVersion = TheNetworg\OAuth2\Client\Provider\Azure::ENDPOINT_VERSION_2_0;
$baseGraphUri = $provider->getRootMicrosoftGraphUri(null);
$provider->scope = 'openid profile email offline_access ' . $baseGraphUri .
'/User.Read';
# Logout
#
if($_GET["logout"])
{
$post_logout_redirect_uri = 'https://www.msn.com'; // The logout destination after the user is
logged out from their account.
$logoutUrl = $provider->getLogoutUrl($post_logout_redirect_uri);
header('Location: '.$logoutUrl); // Redirect the user to the generated URL
}
#
# Get token and go to MENU01
#
else if (isset($_GET['code']) && isset($_SESSION['OAuth2.state']) && isset($_GET['state']))
{
if ($_GET['state'] == $_SESSION['OAuth2.state'])
{
unset($_SESSION['OAuth2.state']);
$token = $provider->getAccessToken('authorization_code', ['scope' => $provider->scope, 'code'
=> $_GET['code'],]);
#header('Location: menu01.php?oid='.$user->getId()."&token=".$token);
}
else
{
echo 'Invalid state';
return null;
}
}
#
# Login
#
else
{
$authorizationUrl = $provider->getAuthorizationUrl(['scope' => $provider->scope]);
error_log("authorizationUrl token:".$authorizationUrl."\r\n", 3,
"C:\\Users\\User\\source\\repos\\IDMS\\1.txt");
$_SESSION['OAuth2.state'] = $provider->getState();
header('Location: ' . $authorizationUrl);
}
?>
But the contents of $token look like this: -
EwCIA8l6BAAU6k7+XVQzkGyMv7VHB/h4cHbJYRAAAX5k1c9mtATTlIlFQyK3KS5IWF qIZ97rD8ZQRxnG2OXlI0aer8zF7HzPIgmWOM0Bm4QhslLdF2VNjPLU1jYZgLv7C2hp
+dUre/MIkHhndMdGkKHaKp6E2LTSCkw6ei6CFCmMypVbeJV1JCRxN6lC9Im7uHRjVn VfASbgsOnupmGDljChR68lMO1TlFefl7+Pa7fI4v7MklCeJA5gBd0WKEqso8xerRxa
6ubv4w1FfZUZ3QfdR7DVi+GowYUUXgNBEdybikTy8TK6dGIQZuagsspSpWwEofGhEN
VeFhX4BMlXg2d5Xt9Hs+O/d3BGEtXLGksaEktNwJqAgi1VjVTQgDZgAACFg/hj18dS
8hWAIkvlNNhWilWG2OuDfVLMxLBRdQoK3RoDfpD8P99hoXcSVr760kFu99cjzLZ4gJ
Xq4ykAiGSHK5JPL8DYLuHRg93jitRBx6DA+0TbjWRO4Zm+2uVxP44C24fDOSWhIaW4
/UJC/EaAz223W/vwcO0J0ZJph5GfEBtbhNqM87r7an+JZvI9zXFwHKvobHcknHOpdn
xaMbWBt2g+N2gum9uJNVQvYDjcXOslpzCqC6Lc+g8So0B4UJOMnrgcJ1gbxOMr/q5H
2k9349wuketwrLpSRB5oo5Fgj8FRFZkp4wa+2xKSFbjBMUagJFAF1txbQ+hOWtUHVS
OFv6XIkrhBEKA3cvPFrmgTdqSdietlDMeYHkcAEL/o7mupaTj9OK7sOwNSSTKtCL6c
MbVVKMsLQ+M1VwZ+pwCg+Xi61BgH7r+wmtFKc1g3h/8GQ9Q8mjq7lShm/sjZrOUoZl
EJkdWfQF2CStP7RDcGItSnPqg0swUksnLEd1yclK+wWn5yll7E6K55ES3BJsXtUFku
wqy8b+QJ1H8/xFLNl32wvvsBh1XWDU+MZR+5edyQmF4jTuCLqlnVTFMD+C6bJGYn3Q
oqloEfm+94+voH4OiFtr0z909U/sQCWl+PWkYWuNUzHqN0fywbpnOaUx1ak3DtV2Oo
mNy18EE8i+FbzeIojjR2PptBiK9g+zQ5iwX73UENojKOKIYd/C/tlWwvgENi38+gTu
9p0T1Fol+d38G/ji/jhzpsMFtZfOU97VL7ZTELmFHBqDmMAzmbphl+kmvVrgvYHgYN
VPebHvrA8psCDAg==
And I'm expecting, or at least I think I should be expecting, as JSON Web Token, delimited by 2 dots.
Something like this: -
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0
.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s
Does anyone know why I'm not getting a JWT, but something else entirely?
I don't speak PHP but it looks to me like your JWT is encrypted. This is a setting in the Azure AD app registration. Look in the app registration in the Azure Portal for a "Token Encryption" blade to verify.
I'm using google drive api to upload a file to google drive using php, but it every time asking me for authentication code fof my application.
I have followed the steps given in the URL below
https://developers.google.com/drive/web/quickstart/quickstart-php
My Code:
require_once 'src/Google/autoload.php';
$client = new Google_Client();
// Get your credentials from the console
$client->setClientId('clientid');
$client->setClientSecret('clientsecret');
$client->setRedirectUri('url');
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
$service = new Google_Service_Drive($client);
$authUrl = $client->createAuthUrl();
try{
//Request authorization
print "Please visit:<br/>$authUrl<br/>\n";
print "Please enter the auth code:\n";
//
$authCode = trim(fgets(STDIN));
// Exchange authorization code for access token
$accessToken = $client->authenticate($authCode);
$client->setAccessToken($accessToken);
//Insert a file
$file = new Google_Service_Drive_DriveFile();
$file->setTitle('document.txt');
$file->setDescription('A test document');
$file->setMimeType('text/plain');
$data = file_get_contents('document.txt');
$createdFile = $service->files->insert($file, array(
'data' => $data,
'mimeType' => 'text/plain',
));
print_r($createdFile);
}catch(apiServiceException $e){
echo $e->getMessage();
}
Response :
https://accounts.google.com/o/oauth2/auth?response_type=code&redirect_uri=REDIRECT_URL&client_id=CLIENT_ID&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=online&approval_prompt=auto
I have did more debugging for this issue and last i can upload files to google drive using PHP.
But for this we have to authorize the code using manually according to google api
then we will get the refresh token and using that token we can upload file to google drive every time whout asking any key
I have added code here https://rgknowledgebase.wordpress.com/2015/06/05/php-upload-file-to-google-drive/