Open bwganblack opened 4 years ago
If I may expand on my previous comment with a reprex?
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 the function 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. Callgs4_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 https://gargle.r-lib.org/articles/non-interactive-auth.html
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.
We could adapt the strategies used in googlesheets again, to make this work.
But what is really needed is to add a new web application credential function to gargle, which would make all gargle-using packages much easier to use with Shiny. This is an acknowledged "to do" and is being tracked here:
I managed to get authorization to any account to work on an app deployed on shinyapps.io by adapting the old googlesheets code as you suggested Jenny. This required setting up my own Google web client (web application type, Google Drive API and Google Sheets API enabled). Doesn't quite solve my problem as there now seems to be a issue when using the method with shinyMobile
apps, but that is another issue.
As you say it would be ideal if gargle was updated so that we could use googlesheets4 for this. In the meantime, I thought perhaps someone might find the code useful as a workaround. Thanks.
library(shiny)
library(DT)
library(googlesheets)
options("googlesheets.webapp.client_id" = "your web client id")
options("googlesheets.webapp.client_secret" = "your web client secret")
options("googlesheets.webapp.redirect_uri" = "url for your app on shinyapps.io")
gs_webapp_auth_url_edit = function (client_id = getOption("googlesheets.webapp.client_id"),
redirect_uri = getOption("googlesheets.webapp.redirect_uri"),
access_type = "online", approval_prompt = "auto")
{
scope_list <- paste("https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets")
url <- httr::modify_url(httr::oauth_endpoints("google")$authorize,
query = list(response_type = "code", client_id = client_id,
redirect_uri = redirect_uri, scope = scope_list,
state = "securitytoken", access_type = access_type,
approval_prompt = approval_prompt))
url
}
ui = fluidPage(
titlePanel("My Google Sheets Explorer"),
sidebarLayout(
sidebarPanel(
uiOutput("loginButton"),
),
mainPanel(
DT::dataTableOutput("listSheets")
)
)
)
server = function(input, output, session) {
output$loginButton <- renderUI({
if (is.null(isolate(access_token()))) {
tags$a("Authorize App",
href = gs_webapp_auth_url_edit(),
class = "btn btn-default")
} else {
return()
}
})
access_token <- reactive({
pars <- parseQueryString(session$clientData$url_search)
if (length(pars$code) > 0) {
gs_webapp_get_token(auth_code = pars$code)
} else {
NULL
}
})
gsLs <- reactive({
gs_ls()
})
output$listSheets <- DT::renderDataTable({
validate(
need(!is.null(access_token()),
message =
paste("Click 'Authorize App' to redirect to a Google page where",
"you will authenticate yourself and authorize",
"this app to access your Google Sheets and Google Drive."))
)
dat <- gsLs()
DT::datatable(dat)
})
}
shinyApp(ui = ui, server = server)
Anyone could use the googlesheets4 and the a deplyoed shiny? Here its crash anytime that I tried to modify the sheet with the error
Listening on http://127.0.0.1:3935
Warning: Error in : Client error: (403) PERMISSION_DENIED
* Client does not have sufficient permission. This can happen because the OAuth token does not have the right scopes, the client doesn't have permission, or the API has not been enabled for the client project.
* Request had insufficient authentication scopes.
105: <Anonymous>
Would it be possible please to update the example shiny apps for googlesheets for use with googlesheets4? The ones found here would be very useful:
https://github.com/jennybc/googlesheets/tree/master/inst/shiny-examples
In particular, I'm trying to replicate the functionality of the My Google Explorer app when deployed to shinyapps.io. My app works ok locally but
gs4_find
andgs4_create
trigger a disconnect from the server on shinyapp.io rather than opening the Tidyverse consent screen. I get the same disconnect when using my own OAuth client.