Intermittent authentication errors in Cloud Functions

461 views Asked by At

I have a simple Cloud Function that receives a webhook and then does a streaming insert into BigQuery. The code is based on this sample (except that I am using streaming inserts)

exports.webHook = function webHook (req, res) {
  return Promise.resolve()
    .then(() => {
      if (req.method !== 'POST') {
        const error = new Error('Only POST requests are accepted');
        error.code = 405;
        throw error;
      }

      const events = req.body || {};
      if (events) {
        const opts = { ignoreUnknownValues: true };
        bigquery
          .dataset('config.DATASET')
          .table('config.TABLE')
          .insert(events, opts)
          .then((data) => {
            console.log(`Success: ${JSON.stringify(data[0])}`);
          })
          .catch((error) => {
            if (error.name === 'PartialFailureError') {
              console.error(`PARTIAL ERROR: ${JSON.stringify(error)}`);
              } else {
              console.error(`OTHER ERROR: ${JSON.stringify(error)}`);
            }

          });
      };
    })
    .then(() => res.status(200).end())
    .catch((err) => {
      console.error(err);
      res.status(err.code || 500).send(err);
      return Promise.reject(err);
    });
};

This function works well most of the time, but I do get the occasional authentication error, which then goes away. enter image description here

textPayload: "OTHER ERROR: {"code":401,"errors":[{"message":"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","domain":"global","reason":"unauthorized"}],"message":"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."}"

I am not sure how auth could be an issue since the Cloud Function and BigQuery are all in the same project.

1

There are 1 answers

0
Michael Whitaker On

The folks on the Cloud Functions team think this may be due to an issue with the access token time-to-live (TTL) and suggested a workaround that has worked for me. Instead of initializing BigQuery at the top of your code (as all their examples have it), put the initializing code right inside the function that makes the call.

Do this:

exports.webHook = function webHook (req, res) {
  const bigquery = require('@google-cloud/bigquery')();
  return Promise.resolve()
    .then(() => {
      if (req.method !== 'POST') {
        const error = new Error('Only POST requests are accepted');
        error.code = 405;
        throw error;
      }
      .
      .

instead of:

const bigquery = require('@google-cloud/bigquery')();
.
.
exports.webHook = function webHook (req, res) {
      return Promise.resolve()
        .then(() => {
          if (req.method !== 'POST') {
            const error = new Error('Only POST requests are accepted');
            error.code = 405;
            throw error;
          }
          .
          .