Firebase to Google Sheets, a tech security clarification
1 min read

Firebase to Google Sheets, a tech security clarification

It is not safe to deploy a service account json file with your Cloud Functions. Read what other options you have to modify a Google Sheets from Firebase Cloud Functions.
Firebase to Google Sheets, a tech security clarification

In a previous article, I show how to synchronize data from Firestore to a spreadsheet in Google Drive using a Cloud Function triggered by the creation of a new document in Firestore.

The approach used in that article, namely, deploying a service account with access to the Google Drive API with the Cloud Functions using it, is not safe.

Here I propose two solutions, both compatible with the rest of the article, that can replace the deployment of the service account with the Cloud Functions.

Add Google Drive API permission to the default service account

When Cloud Functions run, some default authorization credentials are automatically populated. The default service account is in the form [email protected], in my case [email protected], and it is named App Engine default service account.

After enabling access to Google Sheets API from the previous article, instead of creating a new service account, you can use the default one.

We need to share the spreadsheet with [email protected], then we use the Application Default Credentials to authorize our request in src/exportBids.ts:

import * as functions from 'firebase-functions'

// Google Sheet
import { google } from 'googleapis'
const sheets = google.sheets('v4')

const authClient = google.auth.getClient({
    scopes: ['']

export async function exportBids(
    id: string,
    username: string,
    date: string,
    bids: Array<any>
) {`Exporting bids ${id}`)

    const finalData: Array<Array<string>> = []
    bids.forEach(function (bid) {
        finalData.push([id, date, username, bid.bidder, bid.offer])

    await sheets.spreadsheets.values.append({
        auth: await authClient,
        spreadsheetId: "1YpO8oe2I8cEImtKjnBscOLbiNnnTaDP1e82YAaymu20",
        range: `Sheet1!A1:E1`,
        valueInputOption: 'RAW',
        requestBody: { values: finalData, majorDimension: "ROWS" }
    }, {})

Using Google Secret Manager

The other solution is to use Google Secret Manager, which we will explain in detail in a future article.

Subscribe to a curated newsletter

Receive an email every week with curated content about Dart and Flutter.

See previous issues of the newsletter.