R shiny how to pass authentication from another App

How can authentication details be passed to a shiny app in a a secure way?

The shiny app is hosted on a a Linux machine with Shiny Server (Open Source version) and should only be accessible after login on another webpage (through SAML) which is hosted on another Linux machine. The shiny app should have different functionality, depending on user rights. So, that information has to be passed to the shiny app at startup.

How can this be achieved in a secure and reliable way?

The only options I could think of were:

  1. Getting the IP-adress of the user and making a request from the other webpage to get the user-rights of that IP.
  2. Passing user-rights within the URL params and using those with parseQueryString(session$clientData$url_search) at shiny-startup.

The first option would make the app depend on a third-party service that gives me the IP and I dont know how a proxy, Vpn etc would interfer with this approach and how reliable it would be. The second option doesn't really seem secure or professional.

What other options would there be?

2 Likes

I think you need shiny server pro to be able to integrate apps with SSO and make user information available in the shiny session, as it requires passing proxied header information to shiny.

Thanks for your reply, but unfortunately Shiny Server Pro is not an option for us.
And the authentication also shouldn't be done within shiny, but within another app (non-shiny) and the user-role should be passed on to the shiny-app.

I think you might be out of luck in that case if you need different functionality based on user rights as you can only get session$user data to your app with a commercial RStudio option.

If you are willing to switch the authentication step to the app itself you can start to control the outputs based on your authenticated user in the server logic.

I recently wrote an R package with modules for in-app authentication that might help you if that's the route you end up going down.

4 Likes

Auth

You can put any kind of a web-server in front of Shiny, e.g. nginx, apache, Caddy, which you can likely configure to hook into your auth system, and then reverse-proxy to the shiny server instance. nginx + Auth0 can be powerful (e.g. https://auth0.com/blog/adding-authentication-to-shiny-server/), and may provide easier or more flexible integration into existing identity providers, if nginx alone isn't workable.

If you're in a larger company or university, their networking experts should be able to help you configure something like a nginx reverse proxy, which could be on the same machine as your app.

Users

In general, I'd recommend against using IP to distinguish users; this seems rather error-prone.

I think @paul is right about reading the user inside the app, unfortunately.

Another option would be to have distinct apps per user, and redirect through the frontend web server. So if "Alice" logs in, the identity provider knows shes user alice, passes that to e.g. nginx, then nginx reverse-proxies to some app, while it would send user bob to a distinct app or path.

Docker and a good continuous integration system would go a long ways towards making this a manageable, not-too-brittle workaround, but I think there's a fair amount of work here regardless.

Best of luck!

3 Likes

Thanks for your reply @claytonjy, I forwarded your message to our network expert.

The IP-idea would have been the last resort, if nothing else would have been possible.

The option with distinct apps per users is not bad, although every fix would have to be made on all of those instances, which might be hard to maintain and debug. But it is definitly a better option than the IP-idea for example.

Wouldn't it be possible to use cookies for that purpose aswell?

To ease the "every fix would have to be made on all the instances", you could setup continuous delivery so that when you make changes to the core app, the user-specific ones are built and deployed automatically. If you use Github, services like Travis or CircleCI can help with this, and I'm a big fan of Gitlab's built-in CI/CD (free private repos!). If you have a more established dev team they might already use something like Jenkins for this.

Cookies might work; a quick search makes it look a bit tough to read cookies within shiny, but shinyjs might help you do that. Your external-to-shiny auth system will need to set those cookies appropriately, and if security is an issue (external users) you'll want to ensure that's done in a secure way so that I can't spoof my cookie to convince your app I'm a different user.

1 Like