rgooglesheets4gargle

Gargle non-interactive service account token authentication not working


I'm using the googlesheets4 package, which uses gargle for authentication. I have a scheduled script that runs regularly, so I need to set up non-interactive authentication. I tried following all the instructions I've found for setting up a service account token and using that to authenticate, but still can't seem to get it to work.

I created a service account token and stored it in a JSON file. I then used the following command:

gs4_auth (
   scopes="https://www.googleapis.com/auth/spreadsheets", 
   path="/path/to/my/service/token.json")

With options(gargle_quiet = FALSE), I see the following:

trying token_fetch()
trying credentials_service_account()
adding 'userinfo.email' scope
service account email: email_address@project.iam.gserviceaccount.com

Everything seems to work!

But when I try to run gs <- gs4_find(my_sheet_name), I get the following:

attempt from: googledrive
trying token_fetch()
trying credentials_service_account()
Error: Argument 'txt' must be a JSON string, URL or file.
trying credentials_app_default()
trying credentials_gce()
trying credentials_byo_oauth()
Error: inherits(token, "Token2.0") is not TRUE
trying credentials_user_oauth2()
Gargle2.0 initialize
attempt from: googledrive
adding 'userinfo.email' scope
loading token from the cache
no matching token in the cache
initiating new token

...And then it opens up a browser window, asking me to log into my account. Seems like credentials_service_account() succeeds the first time around, but then it gets invoked again and it fails. What am I missing here?

Thanks in advance!


Solution

  • This is now resolved, with a response to a copy of this post on the googlesheets4 package's Github page!

    Turns out, gs4_find is actually a wrapper around googledrive::drive_find. So in order to get the service token to work for this function, I'd need to authenticate with googledrive, not googlesheets4. There is even a whole article here about coordinating auth between googlesheets4 and googledrive, if you're using both.

    For my particular use case, I actually ended up just hardcoding the Google Sheet IDs into my script instead of using gs4_find to do a name lookup, thereby avoiding use of googledrive altogether. Decided that's sufficient for my purposes.