functions-samples
functions-samples copied to clipboard
TypeError: Cannot read property 'access_token' of null at OAuth2Client.getRequestMetadataAsync
Hello,
I am trying to work on a cloud function to automatically update google sheet when on adding data to the firestore database. Here is the code. I am following: https://github.com/firebase/functions-samples/blob/master/google-sheet-sync/functions/index.js.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');
const { Storage } = require('@google-cloud/storage');
const os = require('os');
const path = require('path');
const spawn = require('child-process-promise').spawn;
const db = admin.database();
const CONFIG_CLIENT_ID = functions.config().googleapi.client_id;
const CONFIG_CLIENT_SECRET = functions.config().googleapi.client_secret;
const CONFIG_SHEET_ID = functions.config().googleapi.sheet_id;
const CONFIG_DATA_PATH = functions.config().watchedpaths.data_path;
// The OAuth Callback Redirect.
const FUNCTIONS_REDIRECT = 'https://c39-mwk-dev.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);
let oauthTokens = null;
// 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',
}));
});
const DB_TOKEN_PATH = '/api_tokens';
exports.oauthcallback = functions.https.onRequest(async (req, res) => {
res.set('Cache-Control', 'private, max-age=0, s-maxage=0');
const code = req.query.code;
try {
const {tokens} = await functionsOauthClient.getToken(code);
// Now tokens contains an access_token and an optional refresh_token. Save them.
// await admin.database().ref(DB_TOKEN_PATH).set(tokens);
await admin.database().ref(DB_TOKEN_PATH).set(tokens);
return res.status(200).send('App successfully configured with new Credentials. '
+ 'You can now close this page.');
} catch (error) {
return res.status(400).send(error);
}
});
const SHEET_ID = 'My sheet ID';
exports.appendRecordToSpreadsheet = functions.firestore.document('incident-report/{id}').onCreate(
(snap, context) => {
console.log('I am triggered');
const newRecord = snap.data();
console.log(newRecord);
return appendPromise({
spreadsheetId: SHEET_ID,
range: 'A:C',
valueInputOption: 'USER_ENTERED',
insertDataOption: 'INSERT_ROWS',
resource: {
values: [[newRecord.firstColumn, newRecord.secondColumn, newRecord.thirdColumn]]
},
});
});
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
async function getAuthorizedClient() {
if (oauthTokens) {
return functionsOauthClient;
}
const snapshot = await admin.database().ref(DB_TOKEN_PATH).once('value');
oauthTokens = snapshot.val();
functionsOauthClient.credentials = oauthTokens;
return functionsOauthClient;
}
I get this error:
TypeError: Cannot read property 'access_token' of null
at OAuth2Client.getRequestMetadataAsync (/srv/node_modules/google-auth-library/build/src/auth/oauth2client.js:247:24)
at OAuth2Client.requestAsync (/srv/node_modules/google-auth-library/build/src/auth/oauth2client.js:336:34)
at OAuth2Client.request (/srv/node_modules/google-auth-library/build/src/auth/oauth2client.js:330:25)
at createAPIRequestAsync (/srv/node_modules/googleapis-common/build/src/apirequest.js:248:27)
at Object.createAPIRequest (/srv/node_modules/googleapis-common/build/src/apirequest.js:44:9)
at Resource$Spreadsheets$Values.append (/srv/node_modules/googleapis/build/src/apis/sheets/v4.js:320:37)
at getAuthorizedClient.then (/srv/index.js:111:43)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
How can I solve this problem? I am a beginner.