6

I'm currently trying to create a file and have it uploaded on a Google Drive account using the Service Account auth method provided by Google (since it'll all be server-side on the final product, I don't want users to have to authorize access, so no OAuth per-say).

I'm currently able to connect with the Service Account and upload the file, but the file doesn't show when I'm navigating my Google Drive.

(I was able to have it work (both upload & render) using the OAuth method; where I would manually authorize the application prior to the upload, so I'm pretty sure the code is working)

Also, another way that I know it's working is, once the upload has been done, I'm returned a file ID. If I were to go to "https://drive.google.com/file/d/FILE_ID/view?usp=sharing", I'm met with "Authorization is required".

Is there anything I should be doing when creating the Service Account so that my Gmail account can have access to the files?


For informations, here's the way I'm connecting to the API (Server-side):

<?php
$client = new Google_Client();

if ($this->oauth_credentials = $this->getServiceAccountCredentialsFile()) :
    $client->setAuthConfig($this->oauth_credentials);
endif;

if ($this->warning != null) :
    echo $this->warning;
    return;
endif;

$client->setApplicationName("Test Google Drive Service Account");
$client->setScopes(['https://www.googleapis.com/auth/drive']);
$service = new Google_Service_Drive($client);

define("TESTFILE", ABSPATH.'testfile-small.txt');
if (!file_exists(TESTFILE)) {
    $fh = fopen(TESTFILE, 'w');
    fseek($fh, 1024 * 1024);
    fwrite($fh, "!", 1);
    fclose($fh);
}

$file = new Google_Service_Drive_DriveFile();
$result = $service->files->create(
    $file,
    array(
        'data' => file_get_contents(TESTFILE),
        'mimeType' => 'application/octet-stream',
        'uploadType' => 'media'
    )
);
echo '<pre>'; var_dump($result->id); echo '</pre>';
vvvvv
  • 25,404
  • 19
  • 49
  • 81
SDLarose
  • 81
  • 2
  • 5
  • Please read: [How-do-I-ask-a-good-question?](https://stackoverflow.com/help/how-to-ask) and [Minimal-reproducible-example](https://stackoverflow.com/help/minimal-reproducible-example) – Aerials Aug 14 '20 at 11:10
  • 2
    @Aerials the question already contains sufficient information for the problem to be clear and for an answer to be provided. – pinoyyid Aug 16 '20 at 09:54

2 Answers2

9

You have four options...

  1. Don't use a Service Account. Just store a Refresh Token for the User Account. See How do I authorise an app (web or installed) without user intervention? . It's a myth that Service Accounts are the only option for Server access.
  2. Use a Service Account to write to a folder which has been shared by your User Account to the Service Account
  3. Use a Service Account to write to a folder which is shared by your Service Account to your User Account
  4. Use a Service Account within a G-Suite domain to impersonate the User Account

Option 1. is the easiest, 2 and 3 only differ in terms of who owns the files and therefore against whose quota they are counted. 4 is only relevant for G-Suite

pinoyyid
  • 21,499
  • 14
  • 64
  • 115
  • Thanks for the info, i'll definitely check the other ways to have that works; I didn't know Service Account weren't the only way to do this. – SDLarose Aug 16 '20 at 00:21
  • @pinoyyid hello, can you give link where to find detailed info about option 4 ? – 9900kf Apr 06 '21 at 07:28
  • @Nurs123 this repo uses the impersonation technique to change ownership. You simply want to replace change ownership with create file – pinoyyid Apr 07 '21 at 00:11
  • @pinoyyid can you please share some details (or links) about how to do option 2 or 3? – zhouji Apr 09 '21 at 17:15
  • 1
    You can implement option 2 by logging in with an User account, then in Google Drive: select the folder, click `Share`, paste the service account email and give it `Viewer` / `Editor` / `Commenter` role. You would want to give it the `Editor` role in this case. – jackdbd Feb 06 '22 at 17:37
  • @jackdbd That doesn't work. I am still unable to see the files created by the service account. The permission problems are the other way around, that's why option 3 would be beneficial if it were possible to log in to service account's drive. So I suppose the only possible solution is either 1 or 4, and 4 requires a personal domain, so I just have to give up on service accounts. – Silidrone Aug 12 '23 at 11:07
1

If you want the service account to act on behalf of other users without it asking for consent from them first you have to: Via G Suite admin, enable Domain-Wide-Delegation for the service account.

Otherwise, the service account would need to ask the user for consent at least once, and store the access and refresh tokens, for when token expires it can refresh it with Google servers indefinitely.

More about it here: https://developers.google.com/admin-sdk/directory/v1/guides/delegation

Aerials
  • 4,231
  • 1
  • 16
  • 20