0

I am trying to make google drive API calls using domain wide delegation by using a service account. I can get the authentication working but not the drive api calls. Error: File not found when creating a file in drive

Also before domain wide delegation I made it to work by sharing a drive folder with the service account. But now I want it to work without sharing.

I think i need to do some setServiceAccount stuff somewhere. Not sure where that would happen.

const {google} = require('googleapis');
const auth = new google.auth.JWT(
    client_email, null,
    privateKey, ['https://www.googleapis.com/auth/drive']
);
const drive = google.drive({version: "v3", auth});
//drive.files.create({});
TheMaster
  • 45,448
  • 6
  • 62
  • 85
user3900196
  • 457
  • 2
  • 6
  • 18

1 Answers1

4

Answer:

You need to pass your Service Account private key obtained from the GCP console to your JWT Client, and specify which user you wish to impersonate as a subject.

Code:

After getting your private key, you need to pass this into your JWT Client before authorisation:

let google = require('googleapis');
let privateKey = require("./privatekey.json");

var jwtClient = new google.auth.JWT({
       email: privateKey.client_email,
       key: privateKey.private_key,
       scopes: ['https://www.googleapis.com/auth/drive'],
       subject: 'user@domain.com'
    });

jwtClient.authorize(function (error, tokens) {
  if (error) {
    console.log(error);
    return;
  } 
  else {
    console.log("Successfully connected!");
  }
});

Then you can do as you wish with the Drive API as the service account.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
  • I am already doing this. As i mentioned the authentication part is working. When using Drive API calls like create, it doesn't work and throws error 'File not found'. This part worked when I shared a particular folder with the service account email(before doing any Drive API calls). But with domain wide delegation set, I expect it to work without sharing folders. – user3900196 May 21 '20 at 12:53
  • Can you provide your Drive Create method call? `File not found` doesn't sound like an error thrown by create, as there isn't a file being seached for – Rafa Guillermo May 21 '20 at 13:18
  • var fileMetadata = { name: 'untitled' + '.jpeg', parents: ['some id'] }; drive.files.create({ resource: fileMetadata, fields: 'id, name', }, to give some context, the folder id is grabbed from the state parameter of the 'New url' from here https://developers.google.com/drive/api/v2/enable-sdk – user3900196 May 21 '20 at 14:09
  • Are you trying to create this in a folder in your regular drive, or on a shared drive? The parent ID can just be taken from the URL when viewing the folder. Also, is there any reason you're using Drive V2 documentation with Drive V3? – Rafa Guillermo May 21 '20 at 14:16
  • just in the regular drive. yeah the parent id is taken from url. and yes, probably should switch to V3(although same functionality) – user3900196 May 22 '20 at 13:22
  • Gotcha. You're missing the impersonation bit, I've updated my answer with a new `jwtClient` definition. – Rafa Guillermo May 22 '20 at 14:01
  • thanks! i tried that too. even without that the authentication works. but now adding that, in my case the subject is the service account email. I still get an error 'File not found' on the parentId when i specify parents: [parentId] as part of create api call. – user3900196 May 26 '20 at 04:53
  • 1
    The subject shouldn't be the service account email - the subject needs to be the user that the service account is impersonating. – Rafa Guillermo May 26 '20 at 08:26
  • Ahh! that worked! Initially i was thinking the reverse(service account is the one which is impersonating the actual user). Thanks a lot! – user3900196 May 26 '20 at 22:16