Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RKorAPClient on shinyapps.io, problems with OAuth2 #13

Open
daniel-jach opened this issue Jan 19, 2024 · 4 comments
Open

RKorAPClient on shinyapps.io, problems with OAuth2 #13

daniel-jach opened this issue Jan 19, 2024 · 4 comments

Comments

@daniel-jach
Copy link

daniel-jach commented Jan 19, 2024

I am trying to use RKorAPClient in a shiny app and deploy the app to shinyapps.io. I run into problems when trying to authenticate the app via OAuth2.

I have created a simple template for illustration (see below). The code works locally as expected. I can then deploy and launch the app on shinyapps.io. However, when running on shinyapps.io, the login button has no effect, nothing happens. No message is being displayed (not even "Authentication Failed.").

When I press the login button, the logs say that the application is "Waiting for authentication in browser..." and "Please point your browser to the following url: ..." When I manually enter the provided URL, the KorAP website opens, I log in, and am being redirected to the application (in a new tab), but then again, nothing happens.

I have no experience with OAuth2 and tried to follow the description on the RKorAPClient package page here (https://github.com/KorAP/RKorAPClient). I have registered the application in the KorAP settings, generated a token and a key, and added the key to the code.

The app is at: https://danieljach.shinyapps.io/KED_template/

library(shiny)
library(httr)

korap_app <- oauth_app("korap-client", key = "hdnFfFmd4t9bhNnRfndGfH", secret = NULL, redirect_uri = "https://danieljach.shinyapps.io/KED_template/")
korap_endpoint <- oauth_endpoint(NULL, authorize = "settings/oauth/authorize", access = "api/v1.0/oauth2/token", base_url = "https://korap.ids-mannheim.de")

ui <- fluidPage(
  titlePanel("OAuth Shiny App Template"),
  mainPanel(
    actionButton("loginButton", "Login with OAuth"),
    textOutput("authStatus")
  )
)

server <- function(input, output, session) {
  authenticated <- reactiveVal(FALSE)
  
  observeEvent(input$loginButton, {
    token <- oauth2.0_token(korap_endpoint, korap_app, scope = "search match_info", cache = FALSE)
    
    if (!is.null(token)) {
      authenticated(TRUE)
      output$authStatus <- renderText("Authentication Successful!")
    } else {
      output$authStatus <- renderText("Authentication Failed.")
    }
  })
}

shinyApp(ui, server)
@kupietz
Copy link
Member

kupietz commented Jan 23, 2024

Thanks for the report!

It seems, unfortunately, that we cannot solve the issue at the moment as it is beyond our control between httr(2) and shinyapps. However, as we are not the only ones who have the problem, there will hopefully be a solution soon.

See r-lib/httr2#47 and r-lib/httr2#422 (comment)

For now, you either need to have the KorAP API key either specified statically in your script or you need to get it from the user via a form or parameter.

@daniel-jach
Copy link
Author

Thank you for your reply. Could you please be more specific about the work around you proposed: getting the necessary input from the user via a form or parameter. What exactly would the users need to provide? Where would I feed it into the process?

In my understanding, the KorAP API key is already specified statically (in the above example, key = "hdnFfFmd4t9bhNnRfndGfH" in oauth_app()).

Thank you for your effort.

@kupietz
Copy link
Member

kupietz commented Jan 23, 2024

Thank you for your reply. Could you please be more specific about the work around you proposed: getting the necessary input from the user via a form or parameter. What exactly would the users need to provide? Where would I feed it into the process?

In my understanding, the KorAP API key is already specified statically (in the above example, key = "hdnFfFmd4t9bhNnRfndGfH" in oauth_app()).

Sorry, I should have written access token instead of API key and it's a bit confusing, also because different points of view and terminologies mix here. From KorAP's point of view, "hdnFfFmd4t9bhNnRfndGfH" is the client application ID. The access token you can copy from KorAP's OAuth settings, in the right bottom corner here:

grafik

If you are the end user, or you want to allow the end users to make their queries on behalf of you, you can copy the token and use it staticaly like this:

kco <- new("KorAPConnection", accessToken="mJTPGnt6mhtP9dM6PFTMFx") # just an example token
collocationAnalysis(kco, "Test")

If the end users should be responsible themselves, you should be able to request a user's token via an HTML form and shiny.

@daniel-jach
Copy link
Author

That worked, both locally and on shinyapps.io.

For anyone who struggles to grasph the underlying logic (like I do), here is my updated code:

library(shiny)
library(RKorAPClient)

# UI
ui <- fluidPage(
  titlePanel("Login Shiny App Template"),
  mainPanel(
    textInput("accessToken", "Please enter your access token here."),
    actionButton("loginButton", "Enter."),
    textOutput("authStatus"),
    textInput("userQuery", "Please enter a search word."),
    actionButton("queryGo", "Search."),
    tableOutput("queryResults")
  )
)

# Server
server <- function(input, output, session) {
  # Reactive value to store authentication status
  authenticated <- reactiveVal(FALSE)
  rv <- reactiveValues(kco = NULL)
  # login event
  observeEvent(input$loginButton, {
    # use user token to open connection
    rv$kco <- new("KorAPConnection", accessToken = input$accessToken)
    
    # Check if connection is successful
    if (!is.null(reactive(rv$kco))) {
      authenticated(TRUE)
      output$authStatus <- renderText("Authentication Successful!")
    } else {
      output$authStatus <- renderText("Authentication Failed.")
    }
  })
  
  # query event
  observeEvent(input$queryGo, {
    output$queryResults <- renderTable(corpusQuery(rv$kco, input$userQuery, context = '3', metadataOnly = FALSE) %>% 
                                         fetchNext() %>%
                                         slot('collectedMatches'))
  })
}

# Run the app
shinyApp(ui, server)

The kco connection is stored as a reactive value and defined globally as rv$kco. The login function updates the rv$kco value. The corpus query uses the connection with rv$kco.

End users then need to 1. log into KorAP, 2. go to the OAuth settings, 3. register a new client application (any fake name application will do), and 4. generate a token. This token can then be used as access token as described by @kupietz .

I lost a lot of days over this. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants