1
votes

I'm trying to work with the google API's for the first time, and when I attempt to make a request to the gmail API I'm getting a "precondition check failed" error. I am using a service account authorization, not Oauth2 user consent. Things I've tried:

  1. Authorized "domain wide delegation" for the service account.
  2. Ensured the APP is trusted in the G suite account.
  3. Ensured service account role is "owner"
  4. Enabled domain wide delegation for the client ID of the service account in the g suite admin panel.

This is an adapted sample from the Node client library, but the sample did not use service account auth so I wasn't able to use the sample directly.

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

const gmail = google.gmail('v1');

async function runSample() {
  // Obtain user credentials to use for the request
  const auth = new google.auth.GoogleAuth({
    keyFile: path.resolve(__dirname, 'google-key.json'),
    scopes: ['https://www.googleapis.com/auth/gmail.readonly'],
  });
  google.options({auth});

  const res = await gmail.users.messages.list({userId: 'me'}); // have tried with my gsuite email address as well
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Returning error with message: Error: Precondition check failed.

1
You cant use 'me' that would be checking the service accounts email. You need to deligate it to a user on the gsuite domain. - DaImTo
@DaImTo I also tried using my userID / email instead of 'me' and got the same result. I have domain wide delegation enabled. Does your comment still apply? - chuckieDub
I had a very similar problem and the JWT solution also applies to the GoogleAuth constructor: new GoogleAuth({ keyFile, scopes, clientOptions: { subject: 'emailToImpersonate' } }). The keyFile may be dropped in favor of the GOOGLE_APPLICATION_CREDENTIALS env - lacorte

1 Answers

4
votes

After searching the dark web for eternity, I found a link to a github issue that described how to authenticate as a service using JWT auth.

This is a working version of what I was trying to accomplish:

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

async getMessageList(userId, qty) {

  const JWT = google.auth.JWT;
  const authClient = new JWT({
    keyFile: path.resolve(__dirname, 'google-key.json'),
    scopes: ['https://www.googleapis.com/auth/gmail.readonly'],
    subject: '[email protected]' // google admin email address to impersonate
  });

  await authClient.authorize(); // once authorized, can do whatever you want

  const gmail = google.gmail({
    auth: authClient,
    version: 'v1'
  });

  const response = await gmail.users.messages.list({
    includeSpamTrash: false,
    maxResults: qty,
    q: "",
    userId: userId
  });

  // the data object includes a "messages" array of message data
  return response.data;

}