Simple and secure authentication mechanism for single 'Shiny' applications. Credentials are stored in an encrypted 'SQLite' database. Password are hashed using 'scrypt' R package. Source code of main application is protected until authentication is successful.

Live demo:

You can authenticate with:

  • user: shiny / password: shiny
  • user: shinymanager / password: shinymanager (Admin)

Online documentation :

News on shinymanager 1.0.300

  • Add autofocus on username input.
  • Fix some (strange) bug with input$shinymanager_where
  • Fix inputs_list with some shiny version
  • auth_ui() now accept a choose_language arguments.
  • Rename br language into pt-BR (iso code)
  • add user info in downloaded log file
  • add set_labels() for customize labels
  • Fix simultaneous admin session
  • (#37) hashing password using scrypt


Install from CRAN with :


Or install development version from GitHub :



Secure your Shiny app to control who can access it :

  • secure_app() & auth_ui() (customization)
  • secure_server() & check_credentials()
# define some credentials
credentials <- data.frame(
  user = c("shiny", "shinymanager"), # mandatory
  password = c("azerty", "12345"), # mandatory
  start = c("2019-04-15"), # optinal (all others)
  expire = c(NA, "2019-12-31"),
  admin = c(FALSE, TRUE),
  comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
  stringsAsFactors = FALSE


ui <- fluidPage(
  tags$h2("My secure application"),

# Wrap your UI with secure_app
ui <- secure_app(ui)

server <- function(input, output, session) {
  # call the server part
  # check_credentials returns a function to authenticate users
  res_auth <- secure_server(
    check_credentials = check_credentials(credentials)
  output$auth_output <- renderPrint({
  # your classic server logic

shinyApp(ui, server)

Starting page of the application will be :

Once logged, the application will be launched and a button added to navigate between the app and the admin panel (SQL credentials only and if user is authorized to access it), and to logout from the application :

Secure database

Store your credentials data in SQL database protected with a symmetric AES encryption from openssl, and password hashing using scrypt :

  • create_db()
# Init DB using credentials data
credentials <- data.frame(
  user = c("shiny", "shinymanager"),
  password = c("azerty", "12345"),
  # password will automatically be hashed
  admin = c(FALSE, TRUE),
  stringsAsFactors = FALSE

# you can use keyring package to set database key
key_set("R-shinymanager-key", "obiwankenobi")

# Init the database
  credentials_data = credentials,
  sqlite_path = "path/to/database.sqlite", # will be created
  passphrase = key_get("R-shinymanager-key", "obiwankenobi")
  # passphrase = "passphrase_wihtout_keyring"

# Wrap your UI with secure_app, enabled admin mode or not
ui <- secure_app(ui, enable_admin = TRUE)

server <- function(input, output, session) {
  # check_credentials directly on sqlite db
  res_auth <- secure_server(
    check_credentials = check_credentials(
        passphrase = key_get("R-shinymanager-key", "obiwankenobi")
        # passphrase = "passphrase_wihtout_keyring"
  output$auth_output <- renderPrint({
  # your classic server logic

Admin mode

Using SQL database protected, an admin mode is available to manage access to the application, features included are

  • manage users account : add, modify and delete users
  • ask the user to change his password
  • see logs about application usage

shiny input

Two inputs are created :



You can customize the module (css, image, language, ...).



The application works fine without shinymanager but not you have trouble using shinymanager.

There is a lag between your ui and the server, since shinymanger hides the ui part until authentication is successful. It is therefore possible that some of `ui element`` (input) are not defined and are NULL. In this case, you'll see some warning / error message in your R console.

So we recommend to use in all your reactive/observer functions the req instruction to validate the inputs.

One more global and brutal solution can be :

server <- function(input, output, session) {
  auth_out <- secure_server(....)
    if(is.null(input$shinymanager_where) || (!is.null(input$shinymanager_where) && input$shinymanager_where %in% "application")){
      # your server app code

But it's better to use req solution. More discussion on

HTTP request

shinymanager use http request and sha256 tokens to grant access to the application, like this the source code is protected without having the need to change your UI or server code.

About security

The credentials database is secured with a pass phrase and the openssl package. Hashed password using scrypt. If you have concern about method we use, please fill an issue.

Related work

Package shinyauthr provides a nice shiny module to add an authentication layer to your shiny apps.

Copy Link


Down Chevron



Monthly Downloads







Pull Requests



Last Published

August 24th, 2020

Functions in shinymanager (1.0.300)