tidyverse / googlesheets4

Google Spreadsheets R API (reboot of the googlesheets package)
https://googlesheets4.tidyverse.org
Other
360 stars 53 forks source link

gs4_auth no longer working with same call and parameters in new docker image #288

Closed Gesmira closed 1 year ago

Gesmira commented 1 year ago

Hi, thanks so much for such a useful package!

Our google sheets authentication has worked perfectly fine until recently. In fact, I currently have two different docker images that run the same code in accessing the google sheets (but were built at different times). One works fine with the google authentication, the other returns this error:

Error in gs4_auth(email = getOption(x = "googletokenemail"),  : 
  Can't get Google credentials.
ℹ Are you running googlesheets4 in a non-interactive session? Consider:
• Call `gs4_deauth()` to prevent the attempt to get credentials.
• Call `gs4_auth()` directly with all necessary specifics.
ℹ See gargle's "Non-interactive auth" vignette for more details:
ℹ <https://gargle.r-lib.org/articles/non-interactive-auth.html>

Where the specific line thats being run is: gs4_auth( email = getOption(x = "googletokenemail"), cache = getOption(x = "googletoken"))

The code is being run through a docker container in an ec2 instance, so yes, it is not an interactive session, but in this line we give it the email and the cache parameters, where the cache points to a folder that the ec2 has access to through an S3 bucket.

When I try to reproduce the error locally with gargle_verbosity = debug and copying the folder from the S3 bucket, I get the following output which again brings up a pop up:

Loading required package: shiny

Listening on http://127.0.0.1:4347
trying `token_fetch()`
trying `credentials_byo_oauth()`
Error caught by `token_fetch()`:
inherits(token, "Token2.0") is not TRUE
trying `credentials_service_account()`
Error caught by `token_fetch()`:
Argument 'txt' must be a JSON string, URL or file.
trying `credentials_external_account()`
aws.ec2metadata not installed; can't detect whether running on EC2 instance
trying `credentials_app_default()`
trying `credentials_gce()`
trying `credentials_user_oauth2()`
attempt to access internal gargle data from: googlesheets4
Gargle2.0 initialize
adding "userinfo.email" scope
loading token from the cache
no matching token in the cache
initiating new token
Enter authorization code: 

I want to avoid creating a new token, which I thought should be possible since the current token still works in the other docker container.

I've seen some earlier issues online about package versions and I've included the session info of the two different versions below in case its useful.

Do you have any insight or recommendations about how to fix the issue while maintaining the correct token, or do you recommend generating a new one?

Thank you in advance!

Session Info in working docker container:

R version 4.1.0 (2021-05-18)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.2 LTS

Matrix products: default
BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C             
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] googlesheets4_1.0.0

loaded via a namespace (and not attached):
 [1] fansi_1.0.2       dplyr_1.0.7       utf8_1.2.2        crayon_1.4.2     
 [5] R6_2.5.1          cellranger_1.1.0  lifecycle_1.0.1   magrittr_2.0.2   
 [9] pillar_1.6.5      rlang_1.0.2       cli_3.1.1         fs_1.5.2         
[13] generics_0.1.1    vctrs_0.3.8       ellipsis_0.3.2    googledrive_2.0.0
[17] glue_1.6.1        purrr_0.3.4       compiler_4.1.0    pkgconfig_2.0.3  
[21] gargle_1.2.0      tidyselect_1.1.1  tibble_3.1.6   

Session Info in not working docker container:

R version 4.1.0 (2021-05-18)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.2 LTS

Matrix products: default
BLAS/LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.8.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=C             
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] googlesheets4_1.0.1

loaded via a namespace (and not attached):
 [1] fansi_1.0.4       dplyr_1.1.1       utf8_1.2.3        R6_2.5.1         
 [5] cellranger_1.1.0  lifecycle_1.0.3   magrittr_2.0.3    pillar_1.9.0     
 [9] rlang_1.1.0       cli_3.6.1         fs_1.6.1          generics_0.1.3   
[13] vctrs_0.6.1       googledrive_2.0.0 glue_1.6.2        purrr_1.0.1      
[17] compiler_4.1.0    pkgconfig_2.0.3   gargle_1.3.0      tidyselect_1.2.0 
[21] tibble_3.2.1     
jennybc commented 1 year ago

I do notice that the gargle version is different. In the working container, it's 1.2.0. In the non-working container, it's 1.3.0.

Which gargle version are you using in your local test? I'm going to guess 1.3.0.

The shortest answer is that if you're going to do this (ship a user OAuth token around various environments), I think you should create token with a specific version of gargle and then also make sure that is the version of gargle in all of the relevant docker containers.

A longer answer is that I suspect the default OAuth client varies between the gargle versions, in your context. And that is what causes the cache miss. So another possible way forward, if you don't want to sync all the gargle versions, is that you should take care to create the token with your own OAuth client and then configure that client in all the containers.

Gesmira commented 1 year ago

Hi Jenny, yes, I can confirm that this is fixed when using googlesheets4_1.0.0 and gargle_1.2.0. Do you have a recommended mode of install for these two versions. If I install gargle 1.2.0, googlesheets seems to require gargle 1.3.0 and automatically upgrades. If I install gargle 1.2.0 after, I get an error due to the requirement.

Error: package or namespace load failed for ‘googlesheets4’ in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck = vI[[j]]):
 namespace ‘gargle’ 1.2.0 is already loaded, but >= 1.3.0 is required

Currently I'm using this line to install goooglesheets4, is there something else you'd reccomend? remotes::install_version('googlesheets4', version = '1.0.0', repos = 'http://cran.us.r-project.org')

jennybc commented 1 year ago

Why are you installing an older version of googlesheets4? Meaning: version 1.0.0 released 2022-08-13 versus the current CRAN version 1.1.0 released 2023-03-23.

My advice is to get up-to-date with the current CRAN version of all of these packages.

Or, if that's somehow not desirable, then you should be using a tool like renv to manage the package library.

Gesmira commented 1 year ago

Hi Jenny, thanks for the quick response. This was because I wanted to install gargle 1.2.0 to try to replicate the versions in the docker image that was working and avoid the issues above. As you mentioned, making sure that I have the same version of gargle in all relevant containers. Currently, I am not able to use gargle 1.2.0 with new versions of googlesheets4 due to the dependencies.

If it is not possible to install googlesheets4 and gargle 1.2.0, I can also try to create a new docker image based on the existing image.

jennybc commented 1 year ago

If it is not possible to install googlesheets4 and gargle 1.2.0,

It is possible. But you'd need to be using compatible versions, i.e. "old" versions of both. Doing that properly is what a tool such as renv is for, i.e. freezing a package library.

But unless you really want to do that, I would instead advise going the other direction and getting current googlesheets4 and gargle installed everywhere.

jennybc commented 1 year ago

You are now firmly in the territory described here:

https://gargle.r-lib.org/articles/troubleshooting.html#how-to-avoid-auth-pain

If you have rigged some remote mission critical thing (e.g. a Shiny app or cron job) to use a cached user OAuth token, one day, one of the problems described above will happen and your mission critical token will stop working. Your thing (e.g. the Shiny app or cron job) will mysteriously fail because the OAuth token can’t be refreshed and a new token can’t be obtained in a non-interactive setting. This is why cached user tokens are a poor fit for such applications.

If you choose to use a cached user token anyway, be prepared to deal with this headache periodically. Consider using your own OAuth client to eliminate your exposure to a third-party deciding to roll their client Be prepared to generate a fresh token interactively and upload it to the token cache consulted by your remote mission critical thing. Better yet, upgrade to a more robust strategy for non-interactive auth, such as a service account token.

jennybc commented 1 year ago

I think there's no action item for googlesheets4, so I'm going to close this.

Gesmira commented 1 year ago

Thank you!