2

I am learning to use the Google Drive API and started with a small script isloated away from anything:

import * as fs from "fs";
import * as gdrive from "@googleapis/drive";

const auth = new gdrive.auth.GoogleAuth({
    keyFile: "creds.json",
    scopes: [ "https://www.googleapis.com/auth/drive" ]
});

const ds = gdrive.drive({ version: "v3", auth });

const meta = {
    "name": "uploadme.csv",
    "parents": [ "XXX" ] // Folder ID
};

const body = {
    mimeType: "text/csv",
    body = fs.createReadStream("uploadme.csv")
};

async function yeet() {
    const res = await ds.files.create({
        requestBody: meta,
        media: body
    });
    console.log(res);
}
yeet();

This small script works (returned a status 200 and I see the file uploaded to the folder I specified) and I moved on to integrating it with my main project, mostly directly copying the small script in. The only difference is a different folder structure and a different call stack, where in the small example I had it all in the project root while the main project had a more complex layout and program flow (a Discord bot responding to a command). Unexpectedly, it is giving an authentication error even though (as far as I'm aware) all I meaningfully changed was the project layout.

The small starter script still worked as it did during earlier testing, and even more confusingly, on the main project it's now telling me my key is bad, despite being the exact same auth code and key file I used earlier. Looking around, I see it might be my key has expired and I'm supposed to look for a refresh token, yet I'm unable to find where it is or how to use it when I do find it.

Could someone please point me in the right direction?

Thank you for your time.

Note: I'm using a service account key to access the APIs, not an OAuth credentials


Edit 1:

I ended up copying the entire testing script (still isolated from the main project though) and moved it to the main project's directory, and sure enough, it still worked. Now I'm really bamboozled as to what's going on.

Edit 2:

I linked up the small script with the main project by stubbing out the function and replacing it with a call to the test script (slightly modified by wrapping it in an exported function so it's callable as a module from the main project), and it still works. It's as if the key is locked into the test script.

Edit 3:

I've now swapped the problematic file in the main project for the working testing script, including the file name, and now it works. Very bizzare, but I am now no longer getting the 401 invalid credentials errors. I still don't know what was wrong with the original file in the main project, though.

  • What is the error you are getting? Also, have you tried creating a new service account just for the main application? – Kessy Dec 29 '21 at 14:45
  • @Kessy It's a 401 Invalid Credentials when attempting to obtain the auth object, which works just fine with the small testing project. The service account is fresh aside from testing it with the small test, was hoping to recycle it for the main project. I thought I'd just copy the credentials file. – 404 Name Not Found Dec 29 '21 at 15:29

1 Answers1

3

Invalid service account credentials

Normally means that the key fine you are using is invalid. You need to create a service account key file.

If you open the json key file it should look something like this

{
  "type": "service_account",
  "project_id": "Redacted-305109",
  "private_key_id": "Redacted",
  "private_key": "-----BEGIN PRIVATE KEY-----Redacted---END PRIVATE KEY-----\n",
  "client_email": "Redacted@testapikey-305109.iam.gserviceaccount.com",
  "client_id": "Redacted",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/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/Redacted-305109.iam.gserviceaccount.com"
}

how to create a service account key file

Docs: google-api-nodejs-client#service-account-credentials

const {google} = require('googleapis');

const auth = new google.auth.GoogleAuth({
  keyFile: '/path/to/your-secret-key.json',
  scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Yes, thats how the key file looks. The file is valid, as seen with the small testing project, but copying the code and key file over to the main project and it's suddenly invalid. – 404 Name Not Found Dec 29 '21 at 15:31
  • I would very that it has access to that file that it was copied properly and that the app has access to it. – Linda Lawton - DaImTo Dec 29 '21 at 15:34
  • I'm pretty sure the key is copied properly and the app has access to it, as otherwise I get a ENOENT error instead. – 404 Name Not Found Dec 29 '21 at 15:36
  • 1
    I've managed to get it to work by swapping the main project file with the test script - not sure what was really going on, though. Either way, thanks for trying to help. – 404 Name Not Found Dec 30 '21 at 08:27