Search code examples
pythonoauthoauth-2.0raspberry-pigspread

raspberry pi python gspread OAuth 2 error


I have a script which should append a row in google spreedsheet every 2 minutes. When i start the script it works well but after a some time I get following error:

{
  "error": {
    "code": 401,
    "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.",
    "status": "UNAUTHENTICATED"
  }
}

Python Script

import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']

credentials = ServiceAccountCredentials.from_json_keyfile_name('auth.json', scope)
gc = gspread.authorize(credentials)

wks = gc.open('sheet').sheet1

while True:
    #here is some other code and 2 minutes delay
    wks.append_row(["test", "test2"])

Auth.json

{
  "type": "x",
  "project_id": "x",
  "private_key_id": "x",
  "private_key": "x",
  "client_email": "x",
  "client_id": "x",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "x"
}

Solution

  • The token that Google issued is a short-live token which will expire at a short time. The ServiceAccountCredentials has a refresh method to fetch the new token. In your case, since it is called every 2 minutes, you can call gc.login() every 2 minutes.

    while True:
        gc.login()
    

    I'm not sure why it doesn't refresh by itself (it should). FYI, oauth2client is deprecated, consider using other things. Here is a tip on how to use it with Authlib: https://blog.authlib.org/2018/authlib-for-gspread