auth0 icon indicating copy to clipboard operation
auth0 copied to clipboard

Shiny app goes gray after refresh

Open MislavSag opened this issue 5 years ago • 20 comments

I set up auth0 authentication, everything works fine on login and log out, but when I click refresh in my browser (Firefox), shiny up goes to gray and it returns an error (from shinyapps.io logs):

2019-10-16T13:08:13.633470+00:00 shinyapps[1335290]: Error in httr::oauth2.0_access_token(api, app(redirect_uri), params$code) : 2019-10-16T13:08:13.628803+00:00 shinyapps[1335290]: Warning: Error in httr::oauth2.0_access_token: Forbidden (HTTP 403). Failed to get an access token. 2019-10-16T13:08:13.633472+00:00 shinyapps[1335290]: Forbidden (HTTP 403). Failed to get an access token.

MislavSag avatar Oct 16 '19 13:10 MislavSag

This is a problem and sadly there's no workaround for now. You need to manually delete the "code=xxx" parameter if you want to refresh your app

jtrecenti avatar Oct 18 '19 13:10 jtrecenti

Maybe it is possible to programmatically delete code part when refreshing the page event occur, using JavaScript?

MislavSag avatar Oct 18 '19 13:10 MislavSag

Yeah, you can probably use some client side JS to check if the page has been reloaded. For example: https://stackoverflow.com/questions/5004978/check-if-page-gets-reloaded-or-refreshed-in-javascript

dfalbel avatar Oct 20 '19 20:10 dfalbel

Thanks, I will try to implement this JS code.

MislavSag avatar Oct 20 '19 20:10 MislavSag

For a temporary workaround I used the history.pushState method to update the browser history once the page has loaded. An ugly hack but seems to do the trick.

gbradley avatar Nov 04 '19 19:11 gbradley

Hi @gbradley can you give me a working example where I can use the same method for my shiny apps. Thanks.

mohang13 avatar Nov 27 '19 06:11 mohang13

@mohan1331 Here's what I added:

tags$script(JS("setTimeout(function(){history.pushState({}, 'Page Title', '/');},2000);")),

This simply waits for 2 seconds after the page loads before adding "/" to the browser history stack, meaning the URL parameters are removed without reloading the page.

gbradley avatar Nov 27 '19 08:11 gbradley

@gbradley Where in your Shiny app did you put this code? TIA.

snestler avatar Jul 05 '20 11:07 snestler

@snestler This is how I included it in my apps. What @gbradley gave is a Javascript code so we can put it inside tags$head. I like to call my tags at first. So ui <- tagList( tags$head( tags$script(JS("setTimeout(function(){history.pushState({}, 'Page Title', '/application_name');},2000);")) ) This can be followed by your usual UI code. You can replace your application name in the code so that refreshing the page will refresh the app without any error. Thanks, @gbradley this is the first thing I do whenever I create a shiny application with auth0.

mohang13 avatar Jul 06 '20 08:07 mohang13

@mohang13 I'm still having issues getting this to work. Part of it is my lack of JS knowledge. I'm wondering if it has to do with not having the correct entries for 'Page Title' and '/application_name'. I'm pretty sure I've got the second one right, but am not sure what to put for the first one. Can you provide a specific example for me to reference? Thank you.

snestler avatar Jul 22 '20 12:07 snestler

@snestler I'm attaching a sample shiny application named 'github_app'. As you can see I mentioned the same name in tags$script. Only change the app name (here it is github_app) in your code do not change Page Title (it'll automatically take your page name).

library(shiny)
library(htmlwidgets)

# Define UI for application that draws a histogram
ui <- tagList(
    tags$head(
              tags$script(JS("setTimeout(function(){history.pushState({}, 'Page Title', '/github_app');},2000);"))),
    fluidPage(
        
        # Application title
        titlePanel("Old Faithful Geyser Data"),
        
        # Sidebar with a slider input for number of bins 
        sidebarLayout(
            sidebarPanel(
                sliderInput("bins",
                            "Number of bins:",
                            min = 1,
                            max = 50,
                            value = 30)
            ),
            
            # Show a plot of the generated distribution
            mainPanel(
                plotOutput("distPlot")
            )
        )
    )
    )
    

# Define server logic required to draw a histogram
server <- function(input, output) {

    output$distPlot <- renderPlot({
        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)

        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

I forgot about calling the library htmlwidgets in my previous answer, usually my other libraries like DT calls it automatically. If you still have trouble let me know.

mohang13 avatar Jul 22 '20 14:07 mohang13

Thank you. This is helpful; I wasn't including the whole fluidPage inside the tagList. And the library(htmlwidgets) call was part of the issue. I've got it "working" now, in that clicking "Reload" will restart the app, rather than disconnecting from the server.

But, I seem to experience random disconnects when working in the Shiny app when this is enabled. Not sure why that might be. Any insights?

snestler avatar Jul 25 '20 11:07 snestler

@snestler What do you mean by random disconnects? Do you see an error in auth0.com logs? Anything printed in your Rstudio session? It would help if you included your code and deployment details like OS, R version etc.

chintanp avatar Oct 29 '20 22:10 chintanp

Also, I had to use: tags$script(htmlwidgets::JS("setTimeout(function(){history.pushState({}, 'Page Title', window.location.pathname);},2000);")). This worked in both development (where pathname = '/') and in production where it is not root.

chintanp avatar Oct 30 '20 01:10 chintanp

Any workarounds for this issue ? (Besides what @gbradley suggested)

YO-SC avatar Dec 14 '20 19:12 YO-SC

This is a pretty important issue to address. Why is it marked wontfix?

devhawkio avatar Jan 17 '21 00:01 devhawkio

The problem of this solution, is that if the user don't logout, the page will be logged forever.

lemuelemos avatar Feb 04 '21 17:02 lemuelemos

I used replaceState instead, so it doesn't add a new entry to the history but replaces the one that has the 'code' parameter.

tags$script(JS(
  "setTimeout(function(){history.replaceState(null, '', '/')}, 2000);"
))

Conengmo avatar Jan 19 '23 12:01 Conengmo

I will just point out that this hack works,

setTimeout(function(){history.replaceState(null, '', '/myAppName')}, 2000);

but I did encounter a problem where it prevented all my page resources (images, some CSS and JS) from loading when I moved my app to my own Shiny Server instead of shinyapps.io. This flummoxed me for a couple days. I presume the solution to that would be to extend the wait time from 2 seconds to 5, 10 or 20 seconds. Overall I would say that changing the state like this works but causes unexpected behavior and it would be cool if auth0 can figure something out for this. Cheers!

peernisse avatar Mar 24 '23 22:03 peernisse