No access refresh token is set error displayed on https://github.com/firebase/functions-samples/tree/master/google-sheet-sync

Asked 2 years ago, Updated 2 years ago, 126 views

https://github.com/firebase/functions-samples/tree/master/google-sheet-sync

I got authentication as above site, configured in firebase.config, and deployed on firebase.The actual steps are as follows:

Actual Steps

'use strict';

// Sample trigger function that copies new Firebase data to a Google Sheet

const functions = require('firebase-functions');
const admin=require('firebase-admin');
admin.initializeApp();
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');

// TODO:Use firebase functions:config:set to configure your googleapi object:
// googleapi.client_id = Google API client ID,
// googleapi.client_secret=client secret, and
// Googleapi.sheet_id = Google Sheet id (long string in middle of sheet URL)
constCONFIG_CLIENT_ID = functions.config().googleapi.client_id;
constCONFIG_CLIENT_SECRET=functions.config().googleapi.client_secret;
constCONFIG_SHEET_ID = functions.config().googleapi.sheet_id;

// TODO:Use firebase functions:config:set to configure your watchedpaths object:
// watchedpaths.data_path = Firebase path for data to be synchronized to Google Sheet
constCONFIG_DATA_PATH = functions.config().watchedpaths.data_path;

// The OAuth Callback Redirect.
const FUNCTIONS_REDIRECT=`https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/oauthcallback`;

// setup for authGoogleAPI
const SCOPES=['https://www.googleapis.com/auth/spreadsheets'];
const functionsOauthClient=new OAuth2Client(CONFIG_CLIENT_ID, CONFIG_CLIENT_SECRET,
  FUNCTIONS_REDIRECT);

// OAuth token cached locally.
letoauthTokens='client.secret.json';


// visit the URL for this Function to request tokens
exports.authgoogleapi=functions.https.onRequest(req,res)=>{
  res.set('Cache-Control', 'private, max-age=0, s-maxage=0');
  res.redirect(functionsOauthClient.generateAuthUrl({
    access_type: 'offline',
    scope —SCOPES,
    prompt: 'consent',
  }));
});

// setup for OuthCallback
const DB_TOKEN_PATH='/api_tokens';
const tokens=functions.config().googleapi.access_key;
// after you grant access, you will be redirected to the URL for this Function
// This Function stores the tokens to your Firebase database
exports.oauthcallback=functions.https.onRequest(req,res)=>{
  res.set('Cache-Control', 'private, max-age=0, s-maxage=0');
  const code = req.query.code;

  functionsOauthClient.getToken(code,(err,token)=>{
    // Now tokens contains an access_token and an optional refresh_token. Save them.
    if(err){
      return res.status(400).send(err);
    }
    return admin.database().ref(DB_TOKEN_PATH).set(tokens)
        .then()=>{
          return res.status(200).send('App successfully configured with new Credentials.'
            + 'You can close this page.');
        });
  });
});

// trigger function to write to sheet when new data comes in on CONFIG_DATA_PATH
exports.appendrecordtospreadsheet=functions.database.ref(`${CONFIG_DATA_PATH}/{ITEM}`).onCreate(
    (snap) = > {
      const newRecord=snap.val();
      return appendPromise({
        spreadsheetId:CONFIG_SHEET_ID,
        range: 'A:C',
        valueInputOption: 'USER_ENTERED',
        insertDataOption: 'INSERT_ROWS',
        resource: {
          values: [[newRecord.firstColumn, newRecord.secondColumn, newRecord.thirdColumn]],
        },
      });
    });

// accepts an append request, returns a Promise to append it, enrolling it with auth
function appendPromise(requestWithoutAuth){
  return new Promise ((resolve, reject) = > {
    return getAuthorizedClient().then(client)=>{
      const sheets=google.sheets('v4');
      const request = requestWithoutAuth;
      request.auth=client;
      return sheets.spreadsheets.values.append(request,(err,response)=>{
        if(err){
          console.log(`The API returned an error:${err}`);
          return reject(err);
        }
        return resolve (response.data);
      });
    });
  });
}

// checks if oauthTokens have been loaded into memory, and if not, retrieves them
function getAuthorizedClient(){
  if(oauthTokens){
    return Promise.resolve(functionsOauthClient);
  }
  return admin.database().ref(DB_TOKEN_PATH).once('value').then(snapshot)=>{
    oauthTokens=snapshot.val();
    functionsOauthClient.setCredentials(oauthTokens);
    return functionsOauthClient;
  });
}

// HTTPS function to write new data to CONFIG_DATA_PATH, for testing
exports.testsheetwrite=functions.https.onRequest(req,res)=>{
  constrandom1 = Math.floor(Math.random()*100);
  constrandom2 = Math.floor(Math.random()*100);
  constrandom3 = Math.floor(Math.random()*100);
  const ID = new Date().getUTCMillisconds();
  return admin.database().ref(`${CONFIG_DATA_PATH}/${ID}`).set({
    firstColumn: random1,
    secondColumn: random2,
    thirdColumn: random3,
  }).then()=>res.status(200).send(
    `Wrotte${random1}, ${random2}, ${random3} to DB, trigger should now update Sheet.`);
});

US>Error Contents
firebase errorlog

●// OAuth token cached locally.
Is letoauthTokens='client.secret.json'; correct?
● // setup for OuthCallback
const DB_TOKEN_PATH='/api_tokens';, but /api_tokens in the firebase realtimedb.

by storing and loading access_token and refresh_token retrieved from postman Is it correct?

I apologize for the long letter.If anyone knows, please let me know
I think so. Thank you.

node.js github firebase google-spreadsheet

2022-09-30 16:21

1 Answers

If you use OAuth authentication, you will have let oauthTokens=null; users authenticate on Google's authentication screen.

Also, the refresh token has been registered as a sample, and once you authenticate with authGoogleapi, you will continue to write spreadsheets. I don't think you need to modify OuthCallback from the sample.


2022-09-30 16:21

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.