Authorizing a Google account from an app deployed to shinyapps.io

Hi All,

I have an app which reads and writes to a user's own Google Drive account using googlesheets4 and googledrive .This works fine when run locally but throws an error when deployed on shinyapps.io. Here is a reprex using just googlesheets4:

library(shiny)
library(googlesheets4)
options(gargle_quiet = FALSE)

ui <- fluidPage(
  titlePanel("Googlesheets4 Authentication"),
  sidebarLayout(
    sidebarPanel(
      actionButton("login", "Login")
    ),
    mainPanel(
      with(tags, dl(dt("E-mail", dd(textOutput("g_email")))))
    )
  )
)

server <- function(input, output, session) {
  dat = eventReactive(input$login,{
    if(!gs4_has_token()){
      gs4_auth(email = FALSE, cache = ".secrets")
    }
    dat = gs4_user()
    return (dat)
  })
  output$g_email = renderText({dat()})
}

shinyApp(ui = ui, server = server)

This app starts with an empty .secrets folder in the app directory. When run locally gs4_auth(email = FALSE, cache = ".secrets") successfully skips the console interaction regarding pre-authorised accounts and goes directly to the browser dance. It then stores a token in .secrets as indicated by the console messages:

Listening on http://127.0.0.1:4372
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: googlesheets4
adding 'userinfo.email' scope
loading token from the cache
no matching token in the cache
initiating new token
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
Authentication complete.
putting token into the cache: .secrets

However, when deployed to shinyapps.io, clicking the button causes it to crashes with an error before opening the browser (my actual app disconnects but the log messages are the same). I put a blank csv file in .secrets because otherwise RStudio wouldn't bundle it in the upload.

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()
Error: inherits(token, "Token2.0") is not TRUE
trying credentials_user_oauth2()
adding 'userinfo.email' scope
loading token from the cache
no matching token in the cache
initiating new token
trying credentials_byo_oauth()
gs4_deauth() to prevent the attempt to get credentials.
Call gs4_auth() directly with all necessary specifics.
Error: OAuth2 flow requires an interactive session
Warning: Error in : Can't get Google credentials.
Are you running googlesheets4 in a non-interactive session? Consider:
Gargle2.0 initialize
See gargle's "Non-interactive auth" vignette for more details:
attempt from: googlesheets4
Non-interactive auth • gargle

Is this expected behaviour? More likely I am missing something obvious, but I could find very little in the way of explicit examples for multi-user deployed apps. Are they actually possible? Many thanks.

1 Like