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

Shiny auth? #14

Open
MarkEdmondson1234 opened this issue Jun 22, 2017 · 15 comments
Open

Shiny auth? #14

MarkEdmondson1234 opened this issue Jun 22, 2017 · 15 comments
Milestone

Comments

@MarkEdmondson1234
Copy link
Contributor

It is with great excitement I see the activity here (been watching since @jennybc pinged me about its prototype a while back), I hope to move all auth things of googleAuthR to depend on this package for its next major version, for which it is well due. Hopefully it will also mean more cross compatibility between all the Google API packages out there.

Is multi-user Shiny authentication on the road map for this package? That was pretty much the reason I went down the rabbit hole of googleAuthR, as it was a tougher nut to crack due to the token needing to be a Shiny reactive object, which meant keeping the token in a global of the package didn't work. I got around that at the time with a with_shiny wrapper function that added an argument to each API call function with the token explicitly supplied, but there must be a better way.

If I can help at all, I will try to chip in, at the very least documentation or something once its developed.

@jennybc
Copy link
Member

jennybc commented Jun 22, 2017

Good question! Yes I would expect this to be on the roadmap, but it's admittedly not a top priority right now. We're still getting the "basic" stuff working. The next step for me is to actually connect this to googledrive and slowly move token management functionality out of googledrive/googlesheets* and into here, then re-import it into those packages.

Ccing @craigcitro in case he has had any concrete thoughts re: Shiny.

@craigcitro
Copy link
Collaborator

So for the Shiny case, I can imagine two models we might be interested in here:

  1. "Shared" auth: there's a single identity being used by any/all users of a Shiny app, which should probably be a service account (either GCE or a json-based service account). Here anyone who has access can ultimately see what the service account can see, so we're simplifying auth for the app itself, in exchange for the app's access control being more important.

  2. "Per-user" auth: we want the user to be able to use the app with any table(s) they have access to, and run any queries in a project on their behalf. In this case, the difficulties are in getting the token from the FE to the app, and then making sure that the token isn't persisted or shared on the BE by the app itself.

My shiny experience is (sadly) limited -- which of these sounds more useful?

@MarkEdmondson1234
Copy link
Contributor Author

MarkEdmondson1234 commented Jun 23, 2017

Both are used a lot, but generally:

  1. is covered by the service authentication JSON file or normal .httr-oauth file you can upload with the Shiny app, you just include those auth functions within a reactive object.

  2. is the tricky case, where you need to deal with a reactive token, but is very popular for public apps where you make a Shiny app template, then users can use their own data. I've been interested in it from the Google Analytics/BigQuery perspective, and also using it via Google+ API as a quick authentication method (only show data once sign in is TRUE etc.)

When using Shiny, you also have the option of doing it purely client side with JavaScript to do the OAuth dance, then just pass the object in to R once done. That is my favoured method at the moment as it then also works with RMarkdown.

@MarkEdmondson1234
Copy link
Contributor Author

A touch on this again as I've worked with the method suggested by Joe Cheng that creates an authentication token in a Shiny landing screen before the Shiny app launches proper, meaning you can then just assume all the Google authentication is there and use API call functions normally within the Shiny code, which is more elegant than the with_shiny() function I used previously.

An example of this is the gar_shiny_* function docs.

Practically it means that gargle can be used as normally within Shiny, with just the addition of the Shiny login landing page creation functions.

@jennybc
Copy link
Member

jennybc commented Jan 28, 2019

Thanks @MarkEdmondson1234 for continuing to track and comment on this! I'm resuming work here now that the conference is over, but Shiny remains the area I am least up-to-speed on.

@jennybc jennybc added this to the future milestone Apr 18, 2019
@jennybc
Copy link
Member

jennybc commented Apr 18, 2019

@MarkEdmondson1234 I am pushing towards a near term release of gargle, with it still being clearly marked as "experimental". This is just an FYI that I welcome your thoughts (detailed or vague), esp. re: Shiny. But, that left to my own devices, Shiny won't be directly targeted in v0.1.0.

@MarkEdmondson1234
Copy link
Contributor Author

10-4 :) I'm watching each commit and it all looks really great, I'm a bit full at work at the moment but plan to fork and see how it goes next window I get. I think creating the Shiny UI with a function and pre-authenticating before the Shiny app proper gargle will work in its current form, but need to test it.

@MarkEdmondson1234
Copy link
Contributor Author

Update on strategy here.

A lot of auth methods have been tried over the years, but the two modern versions are broken down to server side and client side.

Both require web based application client as per #94
Both easiest to use when presented as a Shiny module.

  1. Client side - use JavaScript SDK to do the OAuth2 token dance, present the auth token to gargle once ready. Requires a GCP project with authorised JavaScript domains.
  2. Server side - use a function to generate the UI of Shiny, that checks for token in URL, presents real UI once it is authorized. Tokens can then be reached within reactive contexts normally e.g googleAuthR::gar_shiny_*

Perhaps only one of the above? If thats the case the JavaScript one exports dependencies to the Google libraries, tried and tested and would be my first choice.

@jennybc
Copy link
Member

jennybc commented Aug 19, 2019

I was reading up on this over the weekend in fact. Yeah, we are definitely interested in developing the Shiny story here in gargle and sooner, rather than later. Thanks for the recent research and summary. Maybe this will be a good area for you to get involved with a PR and/or review/testing. I may try to recruit another person (with more Shiny/JS experience) to help weigh the options.

@jennybc
Copy link
Member

jennybc commented Aug 19, 2019

Recording some thoughts that are becoming more clear, having just had a call with @schloerke.

Refining @craigcitro's comment waaaay above.

I think there are (at least) 3 big Shiny auth scenarios:

  1. Google Sign-In for Websites: https://developers.google.com/identity/sign-in/web/. Just use Google as a way of identifying individual users. No actual use of, e.g., Google APIs by the Shiny app.
    - googleAuthR has a version of this.
  2. "Shared" auth: there's a single identity being used by any/all users of a Shiny app (from Craig's comment above). I think this is easily handled by gargle today, i.e. you have a token cached to a file and you put it into force.
  3. "Per-user" auth: the hardest one. The increasing lockdown around OAuth clients also means this is going to get even harder to do in a Shiny app.

@OuNao
Copy link

OuNao commented Aug 28, 2019

Hi,

I want to share my experiences about this issue.

Shiny auth scenarios:

  1. Already in googleAuthR package. Works well. Maybe join forces to implement in gargle
  2. googleAuthR and gargle do the job. No problem here.
  3. Already working with googleAuthR.

About the scenario 3. I wrote a shinyapp to do flow cytometry analysis. The data files can be huge (4MB to 1GB). All my data files are already in a googledrive acount. I needed to open these files in my shinyapp.io app, but with no need to download the file to my workstation and upload to shinyapp.io.

## Create access token and render login button
options("googleAuthR.scopes.selected" = c("https://www.googleapis.com/auth/drive.readonly"))#,
options("googleAuthR.webapp.client_id" = "BLABLABLA-myGCPID")
options("googleAuthR.webapp.client_secret" = "BLABLABLA-mySECRET")
options("googleAuthR.client_id" = "BLABLABLA-myGCPID")
options("googleAuthR.client_secret" = "BLABLABLA-mySECRET")

access_token <- callModule(googleAuth, "loginButton")

submit_drive_request<-function(){
    fil<-access_token()
    drive_auth(token = fil, scopes = "https://www.googleapis.com/auth/drive.readonly")
    drive_files(update_dir("root"))
}

I use googleAuthR module to user OAuth authentication and pass the token to drive_auth. It´s working. I think that the shiny module solution is great!

Regards,

@vnniyB
Copy link

vnniyB commented Mar 11, 2020

Hi,
I want to authenticate my shiny docker container by using R at the command line then once the auth is stored in cache the app will not have to authenticate.

When I try to do this R always seems to fail when it tries to open a browser.
Depending on if I run the shiny application or run the commands on the command line I get a one of the two. Either the URL to point my browser to, or the option to enter the authorisation code.

I understand how use_oob works but what I'm failing to get is the URL for the authentication.

Is it possible to do the following is there an option I'm missing?

library(googldrive)

options(
  gargle_oob_default = TRUE,
  gargle_oauth_email = "...@email.com",
  gargle_oauth_cache = TRUE
)

drive_auth()
Point your browser to the following URL: https://accounts.google.com/signin/oauth/identifier?......
Enter authorisation code:

I've tried the shared options mentioned above using the json service account downloaded from https://console.developers.google.com using

drive_auth(path='.....json')

This still requires the browser interaction, which is the issue I'm struggling.

Thanks

@jennybc
Copy link
Member

jennybc commented Apr 17, 2020

@vnniyB Can you use a browser in the container at all?

The service account approach should NOT require any browser interaction. I need to hear more about that to help you find the mis-usage.

You could even get a user token elsewhere (i.e. not in the container) and move it to the container, into whatever location you plan to indicate for the gargle oauth cache. This is a little icky but it's fundamentally no different from your current main plan, which is to pre-cache.

@jennybc
Copy link
Member

jennybc commented May 1, 2020

Interesting hack-y solution that seems to be enough for some folks and their applications:

https://stackoverflow.com/questions/44980757/remote-server-authentication-to-read-googlesheets-from-r-script-not-using-servic/59910070#59910070

@MarkEdmondson1234
Copy link
Contributor Author

MarkEdmondson1234 commented May 1, 2020 via email

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

5 participants