rstudio / shiny

Easy interactive web applications with R
https://shiny.posit.co/
Other
5.38k stars 1.86k forks source link

Make client IP address available on clientData #141

Open jcheng5 opened 11 years ago

jcheng5 commented 11 years ago

Need to look out for x-forwarded-for headers, talk to me for more info.

jcheng5 commented 11 years ago

Also HTTP request headers.

jcheng5 commented 11 years ago

http://rod.vagg.org/2011/07/wrangling-the-x-forwarded-for-header/

coatless commented 8 years ago

Has any movement happened on this? @jcheng5

jcheng5 commented 8 years ago

@coatless No, but what did you need it for?

coatless commented 8 years ago

I have a shiny application that is setup to allow students to submit homework. The app right now only is able to record usernames and submission times on action submit. The request for IP addresses being passed to the shiny app is because it would enable me to store the user's IP along with the submitted assignment. This would provide additional evidence to support an academic integrity violation due to two submissions being ranked similarly under my current setup.

daattali commented 7 years ago

Another vote for exposing request IP

rickn-horizon commented 7 years ago

Yet another vote.

bborgesr commented 7 years ago

If your app is deployed using Connect or shinyapps.io, there's a bit of a hacky way to do this. We're working on making this less hacky by making it accessible from the server-side (and at all in shiny server), so this is not the final word on the topic. I just wanted to share what does work today if case it's useful for any of you:

library(shiny)

ui_xfwd <- NULL

ui <- function(req) {
  if ("HTTP_X_FORWARDED_FOR" %in% ls(req)) ui_xfwd <<- req[["HTTP_X_FORWARDED_FOR"]]
  fluidPage(
    h3("result"),
    uiOutput("result")
  )
}

server <- function(input, output, session) {
  output$result <- renderUI({
    if (!is.null(ui_xfwd)) {
      div(
        p("HTTP_X_FORWARDED_FOR header present in UI:"),
        p(ui_xfwd)
      )
    } else {
      div(
        p("HTTP_X_FORWARDED_FOR header not present; here's the REMOTE_ADDR:"),
        p(session$request[["REMOTE_ADDR"]])
      )
    }
  })
}

shinyApp(ui, server)
jcheng5 commented 7 years ago

I wouldn't do it this way--I'll post a more robust workaround in a bit.

coatless commented 7 years ago

@jcheng5 any eta on the robust method?

jcheng5 commented 6 years ago

Sorry for the delay. The problem with the method by @bborgesr is that it assumes that whenever the server function runs, the immediately preceding UI request was from the same browser. That's not necessarily true--it's entirely possible that those requests are not consecutive due to overlapping traffic or maybe the UI being cached when the user hits the back button.

If you're not too worried about fraud then a more reliable way to do this is to inject the IP address into the generated UI. I wish we had an input binding for <input type="hidden"> but we don't current have that, so you can hide a text input instead.

library(shiny)

ui <- function(req) {
  fluidPage(
    div(style = "display: none;",
      textInput("remote_addr", "remote_addr",
        if (!is.null(req[["HTTP_X_FORWARDED_FOR"]]))
          req[["HTTP_X_FORWARDED_FOR"]]
        else
          req[["REMOTE_ADDR"]]
      )
    )
  )
}

server <- function(input, output, session) {
  cat("The remote IP is", isolate(input$remote_addr), "\n")
}

shinyApp(ui, server)

If you're more concerned about fraud then you'll unfortunately have to wait for the proper fix to land in our server products.

coatless commented 6 years ago

@jcheng5 is there an ETA on when the proper fix will land? (1 month, 6 months, year?)

jcheng5 commented 6 years ago

@coatless Actually I took a closer look and this seems like it should already work with Shiny Server Pro (adding the following to /etc/shiny-server/shiny-server.conf):

whitelist_headers "x-forwarded-for";

Then you could look for session$req$HTTP_X_FORWARDED_FOR from within the server function.

This would be a good candidate for the next version of Shiny Server Open Source (cc @alandipert @shalutiwari) but there certainly will not be another release before rstudio::conf in early February. So at least a couple of months. Sorry I can't get more specific than that.

coatless commented 6 years ago

@jcheng5 excellent. A thousand thanks mate!

jcheng5 commented 6 years ago

Never mind, the whitelist_headers don't work--the codepath it operates on doesn't have the right headers in the first place. Let me see if I can figure this out.

jcheng5 commented 6 years ago

Notes to self (and @alandipert):

Chrisss93 commented 6 years ago

Any update on this? Exposing the request IP inside shiny would be quite useful.

dansmith01 commented 6 years ago

Having access to the client's IP address would be really useful in my projects as well. Any chance we'll see this feature in an upcoming release?

yoderj commented 5 years ago

If your app is deployed using Connect or shinyapps.io, there's a bit of a hacky way to do this. We're working on making this less hacky by making it accessible from the server-side (and at all in shiny server), so this is not the final word on the topic. I just wanted to share what does work today if case it's useful for any of you:

library(shiny)

ui_xfwd <- NULL

ui <- function(req) {
...

Is there a way to access the request information (even in a hacky way) from within a Shiny Module?

cpsievert commented 5 years ago

Is there a way to access the request information (even in a hacky way) from within a Shiny Module?

The approach suggested by @jcheng5 (https://github.com/rstudio/shiny/issues/141#issuecomment-351857670) should work from within a module (once it's fully supported)

yoderj commented 5 years ago

I got the solution by @jcheng5 (https://github.com/rstudio/shiny/issues/141#issuecomment-352564869) to work by passing the request environment (req in his code) through to the sub-module from the main ui function.

But now I'm seeing a value of 127.0.0.1, even when accessed from a different machine. Is this expected?

It seems that it is NOT expected, but it sometimes happens to users: https://groups.google.com/d/msg/shiny-discuss/9WcbS3E4Cfc/9hRS6VDyTxYJ

silvano-junior commented 4 years ago

Does someone knows how to apply this solution using a apache reverse proxy?

If I run this solution on the RStudio server installed on my VM it works fine, but when I pass it to production, where I have a reverse proxy implemented, the IP is always 127.0.0.1

isaactpetersen commented 3 years ago

Any update on this? It would be great to be able to get clients' IP addresses to catch ineligible or fraudulent responses.

jcheng5 commented 3 years ago

Has anyone tried session$req$HTTP_X_FORWARDED_FOR on shinyapps.io recently?

nicocriscuolo commented 3 years ago

Sorry for the delay. The problem with the method by @bborgesr is that it assumes that whenever the server function runs, the immediately preceding UI request was from the same browser. That's not necessarily true--it's entirely possible that those requests are not consecutive due to overlapping traffic or maybe the UI being cached when the user hits the back button.

If you're not too worried about fraud then a more reliable way to do this is to inject the IP address into the generated UI. I wish we had an input binding for <input type="hidden"> but we don't current have that, so you can hide a text input instead.

library(shiny)

ui <- function(req) {
  fluidPage(
    div(style = "display: none;",
      textInput("remote_addr", "remote_addr",
        if (!is.null(req[["HTTP_X_FORWARDED_FOR"]]))
          req[["HTTP_X_FORWARDED_FOR"]]
        else
          req[["REMOTE_ADDR"]]
      )
    )
  )
}

server <- function(input, output, session) {
  cat("The remote IP is", isolate(input$remote_addr), "\n")
}

shinyApp(ui, server)

If you're more concerned about fraud then you'll unfortunately have to wait for the proper fix to land in our server products.

Thanks @jcheng5 for this. I want to try to implement this in my shiny application. I've a just a quick question. What do you mean for "worried about fraud"? Is adding this function problematic on the users or developer side?

Thank you for your availability. I'll write back here as soon as I have a working example.

jcvdav commented 1 year ago

Are there any updates on this?

cpsyctc2 commented 5 months ago

I'm another user of the open source server (https://shiny.psyctc.org/) and am on essentially zero budget providing free apps so I'm never going to be able to afford shiny server pro sadly. I would really like to see making the x-forwarded-for header available in the open source server (and ideally some guide as to how to process it!) Is it such a huge programming challenge?! TIA (and thanks for an amazing open source server though I do crave this!)