0

I'm hoping to use the Google Sheets API in a cloud function, which will run from my account's default service account, and I'm working in Python. However, I've only ever authenticated the Sheets library locally, using this bit of code:

import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials    

def gen_creds(path_to_secret: str, rw_vs_ro: str):
    """
    Generate the needed credentials to work with the Sheets v4 API based on your secret
    json credentials file.

    :param path_to_secret: The file path to your credentials json file
    :param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
    :return: The built service variable
    """
    if rw_vs_ro == 'r_o':
        scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
        creds_nm = 'readonly_token.json'
    else:
        scopes = ['https://www.googleapis.com/auth/spreadsheets']
        creds_nm = 'readwrite_token.json'

    creds = None

    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists(creds_nm):
        creds = Credentials.from_authorized_user_file(creds_nm, scopes)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                path_to_secret, scopes)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open(creds_nm, 'w') as token:
            token.write(creds.to_json())

    return build('sheets', 'v4', credentials=creds)

And I'm not entirely sure how to translate this to something that a cloud function would understand, as the cloud function won't be running as me, and lacks the same type of os path that I have access to locally. Would appreciate any insight into what the translation process looks like here--I was only able to find examples in JS, which wasn't perfect for what I was going for. Then, I would love to understand how to actually implement this code in a cloud function in GCP. Thanks!

2

2 Answers 2

2

Actually, I found a simple answer to this question in the end--it's very easy to generate these credentials in GCP for Python! The exact replacement method for gen_creds is:

import google.auth
from googleapiclient.discovery import build

def gen_creds(rw_vs_ro: str):
    """
    Generate the service credentials to be used to query a google sheet

    :param rw_vs_ro: A string, 'r_o' or 'r_w', representing whether creds should be readonly or readwrite
    :return: The built service variable
    """

    if rw_vs_ro == 'r_o':
        scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly']
    if rw_vs_ro == 'r_w':
        scopes = ['https://www.googleapis.com/auth/spreadsheets']

    creds, project = google.auth.default(scopes=scopes)
    service = build('sheets', 'v4', credentials=creds)
    return service

Hope this is as helpful to others as it is to me!

Sign up to request clarification or add additional context in comments.

Comments

0

When you deploy a cloud function, your main code will have access to all the files deployed within that function. This means all you need to do is include your readwrite_token.json/readonly_token.json files when deploying the package. Once that's done, instead of simply passing the token files as strings, since the function’s directory can be different from the current working directory, you have to properly include the files as specified in this GCP Function Filesystem documentation Also, you can't use InstalledAppFlow in the Cloud Function environment since this flow is meant for desktop os environments so better pray for the block to never be executed or replace with a different flow.

1 Comment

Thank you for this response @Akinniyi Akinyemi! Just to check, don't the token.json files expire after a week or two? How do I deal with that in these functions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.