-
Notifications
You must be signed in to change notification settings - Fork 2
Introduction
This project was born as an attempt to introduce an authentication step in front of the open-source version of shiny-server.
Some time ago, I made a first attempt by using HTTP Basic Authentication
with docker compose with shiny and nginx.
However, this solution was not ideal since HTTP Basic authentication is not
secure even when using the HTTPS protocol. Moreover, there was no session between the
browser and the server, making the authentication persistent until the browser is
closed by the client. Closing and reopening the browser would require a new
authentication, and this is the only way to use different credentials to access
different restricted areas. Furthermore, credentials need to be managed only on the server
side using openssl commands, which store credentials in an encrypted file and
require that every restricted location is configured properly to check credentials
against such file: this would be difficult to manage if there are different users
with different access privileges. For these reasons, I searched for an alternative
way to introduce an authentication process on top of the shiny server.
The idea was to introduce a session-based authentication process between the nginx and shiny layers, using a framework that can manage authentication relying on databases
After doing some research on the web, I found a clever solution in this tutorial made by pawamoy to implement authentication using the Django framework, so I decided to follow his guide and implement this version of django-server using docker compose. This project is not an attempt to replace the official Posit shiny products: it has limitations that the official enterprise software doesn't have. This project is an attempt to provide authentication on top of the community shiny server using only open-source solutions.
Posit provides the enterprise version of the software made available to the community. They can support customers and provide additional features, for example the authentication layer is integrated natively and easy to configure. Updates are managed by the Posit team and shiny applications can scale up based on users' needs
-
shinyapps.io: This is the PaaS version of shiny
server. Users can create accounts and upload their applications directly using
Posit with the
rsconnectpackage. There's a free plan for sharing up to 5 applications for a total of 25 hours of execution - Posit Connect: This is a platform that allows sharing of shiny applications, R Markdown, Jupyter notebooks, and more.
These are other solutions I found to add authentication to shiny applications. Maybe one of them could be useful to you:
- polished: This is an R package that adds authentication to shiny applications relying on Firebase. More information can be found on their GitHub site and in this article on R bloggers
- shinyproxy: This project adds authentication to shiny relying on Docker, Java, and Shiny. Its customization is very interesting since it can support LDAP authentication
- shiny-user-auth: a simple shiny application that uses modals, Bootstrap, and SQLite to manage authentication with Shiny
- using iframes: you could integrate shiny into an HTML document using iframes, as described in this Google group and in Posit community forums
Django authentication can handle users, groups, permissions, and cookie-based user sessions. It provides tools for dealing with users, such as password reset or profile management. Moreover, Django adds some security features that make this framework reliable. Here are some attempts to manage shiny server using Django:
- djangocms-shiny-app: which adds shiny to Django with CMS-specific features
- django-serve-shiny: which allows passing data from Django to a shiny application
In this guide, the author wraps the shiny server application using an iframe in a single Django view, and manages the subsequent websocket requests between the client and the shiny server using NGINX. By configuring NGINX to perform external authentication relying on the Django server, we can determine whether the client has access to the shiny websocket requests or not.
Although the pawamoy solution addresses the main problem I have (adding an authentication layer to shiny), I needed to better structure this solution by adding the following features:
- structure the project with docker-compose: this will ensure reproducibility in my testing and production environments, and I found it is easier to configure and manage compared to installing everything in a single Docker image or virtual machine
- ensure authentication per application: relying on Django models and Django authentication, I want to grant access to individual applications, or define public applications (applications that don't require user authentication)
- accessing applications directly (like the Shiny gallery does): in this way I can avoid the Django container itself and display the application on the whole page, while the authentication is handled behind the scenes
- customize layout: structure the Django application views with Bootstrap
These features are implemented in the current shiny-server application project.
P.S. I've also written a medium post about this project, check it out, it's free!
All shiny-server project are available under GPL version 3 license. You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.