11

I'm testing out the Google Drive API. The test script does the HTTP GET to access the Files->List API but somehow I always get an empty list in items. I have hundreds of files in my google drive so the result is unexpected. The HTTP response is shown below.

    {
     "kind": "drive#fileList",
     "etag": "\"VEU5fga3uYlZRf0pG-N1kS4iWP4/Kxo5eGvPKynWfroe9v5L5T43-n0\"",
     "selfLink": "https://www.googleapis.com/drive/v2/files?maxResults=5",
     "items": []
    }
kvzrock
  • 437
  • 1
  • 4
  • 10
  • My scope is https://www.googleapis.com/auth/drive. I've also tried using the https://docs.google.com/feeds scope and HTTP GET https://docs.google.com/feeds/default/private/full and that doesn't work either. – kvzrock Oct 02 '12 at 22:03
  • 1
    Looks like accessing google drive api through service account is NOT the same as accessing google drive through the user to which the service account is tied to. The service account gets its own little world that is separate from the user's google drive space. – kvzrock Oct 03 '12 at 00:19

4 Answers4

16

To allow service account to access the files in my own Google Drive, I have to give permission to the email address of the service account. Once the permissions are setup correctly, the list gets populated with the files that the service account is allowed to access.

kvzrock
  • 437
  • 1
  • 4
  • 10
  • Can you detail how you gave permissions to the service account? I shared my files and folders with the service account email address (xxxxxxxxxx@developer.gserviceaccount.com) but doesn't seem to work. – ifunk Oct 14 '12 at 06:39
  • 10
    I've found my issue. I had the scope set to ".../auth/drive.file". Changing it to ".../auth/drive" fixed the problem. – ifunk Oct 14 '12 at 06:48
  • @ifunk I have the same problem, can you please explain what you did exactly? Thanks in advance! – mongotop Nov 02 '12 at 21:21
  • This was the key for me: $client->setAssertionCredentials(new Google_AssertionCredentials( 'xxxxxxxx@developer.gserviceaccount.com', array('https://www.googleapis.com/auth/drive'), file_get_contents('path/to/key.p12') ); All I did apart from that code is using getAccessToken() and setAccessToken() for caching the access token and setClientId() and then pass the client to the Google_DriveService class. – ifunk Nov 05 '12 at 07:57
  • im having same issue, but strange. on any account except mine i can get list from folder with subfolder, but each subfolder returns empty string. anyone had something similar? – aleXela Sep 15 '17 at 20:54
  • 4
    Why the hell isn't this clearly stated on their docs? So... many.... hours.... wasted, thanks. – Joaquim Ley Aug 03 '20 at 14:16
  • I have the same issue, and no matter what I do, it still returns empty. I tried to do all the things recommended here, but I am not sure if I have done it right. Can you please mention how to add permission to service account step by step? – Soli Oct 27 '20 at 16:40
  • 2
    I created a new folder in my gmail account. Then share the folder with the service account. And it works – Miguel Carrillo Jan 05 '21 at 01:02
  • Facts, the problem is just give permission in google drive to some folder, like right click, share, add email of service account, you can just create a root folder maybe? – Alberto Acuña Nov 24 '22 at 22:29
  • like shown in previous comments, use the service account email in the credential creation. Then make sure the folder you are writing to is shared with the service account email. This worked for me. – user890332 Jul 11 '23 at 18:21
12

Google does not make it clear in their documentation. After half a day of trying to modify everything that might help, I discovered that you need to share the file with the email described in your service account json file.

For example, I have a Google Slide file in my personal Google Drive, and I want it to be readable by Google Drive API, I'll have to share this Slide file with xxx@xxx.iam.gserviceaccount.com listed in the json service account file.

Then the following code snippet should return the shared Slide file:

import {google} from 'googleapis'
const credentials = require("./credentials.json");

async function main() {
    const scopes = [
        'https://www.googleapis.com/auth/drive',
        'https://www.googleapis.com/auth/presentations',
    ]

    const auth = new google.auth.JWT(
        credentials.client_email,
        null,
        credentials.private_key,
        scopes,
    )


    const drive = google.drive({
        version: 'v3',
        auth
    })

    const res = await drive.files.list()
    console.log(res.data)

}

main()

{
  kind: 'drive#fileList',
  incompleteSearch: false,
  files: [
    {
      kind: 'drive#file',
      id: 'xxxxx',
      name: 'xxxxx',
      mimeType: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
    },
  ]
}

Bobby
  • 197
  • 1
  • 7
5

This usually means you've authenticated with a scope that doesn't give you permission to see those files.

For example, the scope https://www.googleapis.com/auth/drive.file only provides access to files created or opened by the app. You won't be able to access files created in the Google Drive interface or by other apps.

If you want to access all the files, you'll have to use another scope. https://www.googleapis.com/auth/drive, for example, gives you full, permissive scope to access all of a user's files.

You can find information about the available scopes here. Use it to pick the right scope for your app.

zachguo
  • 6,200
  • 5
  • 30
  • 31
Tiago
  • 3,113
  • 2
  • 31
  • 45
1

it's enough to include https://www.googleapis.com/auth/drive.readonly.metadata scope to list files

scorpp
  • 635
  • 10
  • 16
  • 3
    I've been using this for a while, but the documentation [was changed to "drive.metadata.readonly"](https://stackoverflow.com/questions/28310071/difference-between-drive-metadata-readonly-and-drive-readonly-metadata#comment106459359_28312545) at some point. – Nickolay Feb 12 '20 at 13:37