1

I can't for the life of me figure out why this isn't working. I feel like I've done everything comparable to what's done in this tutorial, but it's not working.

I have done the following:

  1. Created a project with the Google Sheets API enabled.
  2. Created a Service Account under the Credentials section of my project.
  3. Downloaded the JSON configuration file for the Service Account.
  4. Saved the private key (-----BEGIN PRIVATE KEY----...., all on one line), the client email, and the project ID to my environment variables.

My code looks like so:

import GoogleAPIs from 'googleapis';
import googleAuth from 'google-auth-library';

export default class GoogleSheetsAPI {

  connect() {
    return new Promise(async resolve => {
      const client = new googleAuth.JWT(
        process.env.GOOGLE_CLIENT_EMAIL,
        null,
        process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n'),
        ['https://www.googleapis.com/auth/spreadsheets.readonly']
      );
      const url = 'https://www.googleapis.com/dns/v1/projects/' + process.env.GOOGLE_PROJECT_ID;
      client.request({url})
        .then(res => console.log(res.data))
        .catch(err => console.error(err));
    });
  }
  ...
}

I've verified that the values are being loaded correctly from the environment variables.

This is the response I get after calling connect() on a new instance of GoogleSheetsAPI:

{ Error: Request had insufficient authentication scopes.
    at Gaxios.request (<project_folder>/node_modules/gaxios/build/src/gaxios.js:70:23)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
  response:
   { config:
      { url: 'https://www.googleapis.com/dns/v1/projects/<redacted but good>',
        headers:
         { Authorization:
            'Bearer <redacted but looks reasonable>',
           'User-Agent': 'google-api-nodejs-client/5.1.1',
           Accept: 'application/json' },
        params: [Object: null prototype] {},
        paramsSerializer: [Function: paramsSerializer],
        validateStatus: [Function: validateStatus],
        responseType: 'json',
        method: 'GET' },
     data:
      { error:
         { code: 403,
           message: 'Request had insufficient authentication scopes.',
           errors:
            [ { message: 'Request had insufficient authentication scopes.',
                domain: 'global',
                reason: 'forbidden' } ],
           status: 'PERMISSION_DENIED' } },
  ...

Surely it's something simple. Any ideas? Thanks!

mightimaus
  • 937
  • 2
  • 14
  • 26
  • Can I ask you about what you want to do using the scope of `https://www.googleapis.com/auth/spreadsheets.readonly`? – Tanaike Jul 30 '19 at 22:50
  • @Tanaike I just want to read rows in a sheet that's populated by a Google Form. – mightimaus Jul 31 '19 at 01:04
  • Thank you for replying. In your script, it seems that you are trying to use Cloud DNS. So I cannot understand about your situation. Can I ask you about your goal? You want to read values from an existing Google Spreadsheet using the service account by googleapis with Node.js. If my understanding correct, where is the Spreadsheet? It is in Google Drive of your Google account or of Service account? – Tanaike Jul 31 '19 at 01:17
  • @Tanaike Perhaps I am attempting to use a Service Account incorrectly. I'm trying to access a Google Sheet (that is owned by my personal account but shared with the Service Account email) from a Node.js app running on Heroku. If it only works when it's running on GCP, then that indeed would be a problem. – mightimaus Jul 31 '19 at 12:58
  • I ended up just going with OAuth. – mightimaus Jul 31 '19 at 17:01
  • Thank you for replying. You want to read the values from your Google Spreadsheet using OAuth2 with googleapis of Node.js. Is my understanding correct? If my understanding is correct, can I ask you whether your access token retrieved with OAuth2 can be used for retrieving the values from Spreadsheet? By this, I would like to propose a sample script. – Tanaike Jul 31 '19 at 22:55

0 Answers0