shinyauthr

repository·master·Indexed 19 days ago

https://github.com/paulc91/shinyauthr

An R package providing modular UI and server components to add authentication layers, including login and logout functionality, to Shiny applications. It features support for cookie-based automatic login and password hashing using the sodium package.

Tokens
1.7K
Snippets
6
Records
6
Agent score
16%

What's inside shinyauthr

  1. How the authentication modules work together

    master

    The package provides two main modules consisting of a UI component and a Server component:

    1. Login Module: loginUI() and loginServer() handle user credentials.
    2. Logout Module: logoutUI() and logoutServer() handle session termination.

    The credentials object

    When loginServer() is called, it returns a reactive list containing two elements:

    • user_auth: A boolean (TRUE if authenticated, FALSE otherwise).
    • info: A row of data from your provided data frame associated with the authenticated user (or NULL if not authenticated).

    Workflow Pattern

    • Use req(credentials()$user_auth) inside your reactives, renders, and observers to ensure code only executes after a successful login.
    • The logoutServer() module should be passed a reactive trigger based on the user_auth status to automatically show/hide the logout button.
    # Minimal usage pattern
    credentials <- shinyauthr::loginServer(
      id = "login",
      data = user_base,
      user_col = user,
      pwd_col = password,
      log_out = reactive(logout_init())
    )
    
    logout_init <- shinyauthr::logoutServer(
      id = "logout",
      active = reactive(credentials()$user_auth)
    )
  2. Configure cookie-based automatic login

    master

    To avoid repeated logins, you can implement cookie-based authentication by providing cookie_setter and cookie_getter functions to loginServer().

    Requirements:

    1. cookie_setter: A function accepting (user, sessionid) that saves the session to a persistent store (e.g., a database).
    2. cookie_getter: A function that returns a data.frame containing valid user and sessionid columns.

    loginServer parameters for cookies:

    • cookie_logins: Set to TRUE.
    • sessionid_col: The name of the column in your data containing session IDs.
    • cookie_getter: Your custom getter function.
    • cookie_setter: Your custom setter function.
    # Example setup for cookie-based login
    credentials <- shinyauthr::loginServer(
      id = "login",
      data = user_base,
      user_col = user,
      pwd_col = password,
      cookie_logins = TRUE,
      sessionid_col = sessionid,
      cookie_getter = get_sessionids_from_db,
      cookie_setter = add_sessionid_to_db,
      log_out = reactive(logout_init())
    )
  3. Implement basic authentication in a Shiny app

    master

    To add authentication, define a data frame containing user credentials, add the loginUI and logoutUI to your UI, and initialize the loginServer and logoutServer in your server function.

    library(shiny)
    
    # 1. Define user data
    user_base <- tibble::tibble(
      user = c("user1", "user2"),
      password = c("pass1", "pass2"),
      permissions = c("admin", "standard"),
      name = c("User One", "User Two")
    )
    
    ui <- fluidPage(
      div(class = "pull-right", shinyauthr::logoutUI(id = "logout")),
      shinyauthr::loginUI(id = "login"),
      tableOutput("user_table")
    )
    
    server <- function(input, output, session) {
      # 2. Initialize login server
      credentials <- shinyauthr::loginServer(
        id = "login",
        data = user_base,
        user_col = user,
        pwd_col = password,
        log_out = reactive(logout_init())
      )
    
      # 3. Initialize logout server
      logout_init <- shinyauthr::logoutServer(
        id = "logout",
        active = reactive(credentials()$user_auth)
      )
    
      # 4. Use credentials to protect content
      output$user_table <- renderTable({
        req(credentials()$user_auth)
        credentials()$info
      })
    }
    
    shinyApp(ui = ui, server = server)
  4. Hash passwords with `sodium`

    master

    For security, you should store hashed passwords rather than plain text. Use the sodium package to hash passwords before saving them to your user database. When calling loginServer(), set sodium_hashed = TRUE to tell the module to use sodium for verification.

    # 1. Hashing passwords (run once during setup)
    library(sodium)
    user_base <- tibble::tibble(
      user = c("user1", "user2"),
      password = purrr::map_chr(c("pass1", "pass2"), sodium::password_store)
    )
    saveRDS(user_base, "user_base.rds")
    
    # 2. Using hashed passwords in the app
    user_base <- readRDS("user_base.rds")
    
    credentials <- shinyauthr::loginServer(
      id = "login",
      data = user_base,
      user_col = user,
      pwd_col = password,
      sodium_hashed = TRUE,
      log_out = reactive(logout_init())
    )
  5. Run shinyauthr example apps

    master

    To explore how shinyauthr integrates with different UI frameworks (like shinydashboard or navbarPage), use the runExample function to launch built-in examples.

    # Launch various example apps
    shinyauthr::runExample("basic")
    shinyauthr::runExample("shinydashboard")
    shinyauthr::runExample("navbarPage")