Last active
August 23, 2023 17:22
-
-
Save calligross/e779281b500eb93ee9e42e4d72448189 to your computer and use it in GitHub Desktop.
Shiny Cookie Based Authentication Example, please visit https://calligross.de/post/using-cookie-based-authentication-with-shiny/ for more information.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(shiny) | |
library(shinyjs) | |
if (!dir.exists('www/')) { | |
dir.create('www') | |
} | |
download.file( | |
url = 'https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js', | |
destfile = 'www/js.cookie.js' | |
) | |
addResourcePath("js", "www") | |
# This would usually come from your user database. But we want to keep it simple. | |
password_hash <- bcrypt::hashpw('secret123') # Never store passwords as clear text | |
sessionid <- "OQGYIrpOvV3KnOpBSPgOhqGxz2dE5A9IpKhP6Dy2kd7xIQhLjwYzskn9mIhRAVHo" # Our not so random sessionid | |
jsCode <- ' | |
shinyjs.getcookie = function(params) { | |
var cookie = Cookies.get("id"); | |
if (typeof cookie !== "undefined") { | |
Shiny.onInputChange("jscookie", cookie); | |
} else { | |
var cookie = ""; | |
Shiny.onInputChange("jscookie", cookie); | |
} | |
} | |
shinyjs.setcookie = function(params) { | |
Cookies.set("id", escape(params), { expires: 0.5 }); | |
Shiny.onInputChange("jscookie", params); | |
} | |
shinyjs.rmcookie = function(params) { | |
Cookies.remove("id"); | |
Shiny.onInputChange("jscookie", ""); | |
} | |
' | |
server <- function(input, output) { | |
status <- reactiveVal(value = NULL) | |
# check if a cookie is present and matching our super random sessionid | |
observe({ | |
js$getcookie() | |
if (!is.null(input$jscookie) && input$jscookie == sessionid) { | |
status(paste0('in with sessionid ', input$jscookie)) | |
} | |
else { | |
status('out') | |
} | |
}) | |
observeEvent(input$login, { | |
if (input$username == 'admin' & bcrypt::checkpw(input$password, hash = password_hash)) { | |
# generate a sessionid and store it in your database, but we keep it simple in this example... | |
# sessionid <- paste(collapse = '', sample(x = c(letters, LETTERS, 0:9), size = 64, replace = TRUE)) | |
js$setcookie(sessionid) | |
} else { | |
status('out, cause you don\'t know the password secret123 for user admin.') | |
} | |
}) | |
observeEvent(input$logout, { | |
status('out') | |
js$rmcookie() | |
}) | |
output$output <- renderText({ | |
paste0('You are logged ', status())} | |
) | |
} | |
ui <- fluidPage( | |
tags$head( | |
# you must copy https://raw.githubusercontent.com/js-cookie/js-cookie/master/src/js.cookie.js to www/ | |
tags$script(src = "js/js.cookie.js") | |
), | |
useShinyjs(), | |
extendShinyjs(text = jsCode), | |
sidebarLayout( | |
sidebarPanel( | |
textInput('username', 'User', placeholder = 'admin'), | |
passwordInput('password', 'Password', placeholder = 'secret123'), | |
actionButton('login', 'Login'), | |
actionButton('logout', 'Logout') | |
), | |
mainPanel( | |
verbatimTextOutput('output') | |
) | |
) | |
) | |
shinyApp(ui = ui, server = server) |
Using
tags$script(src = "https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js")
in the UI instead oftags$script(src = "js/js.cookie.js")
seems to work though.
Thanks, I updated the download URL.
When i am running this application i am getting error as cannot open url for cookies download.
Can anyone assist me?
In addition: Warning message:
In download.file(url = "https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js", :
cannot open URL 'https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js': HTTP status was '403 Forbidden'
Error: shinyjs: extendShinyjs: functions
argument must be provided.
got it: extendShinyjs(text = jsCode, functions=c("getcookie","setcookie","rmcookie"))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
'https://raw.githubusercontent.com/js-cookie/js-cookie/master/src/js.cookie.js' does not exist anymore. Even when including the old
js.cookie.js
script it does not work.Using
tags$script(src = "https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js")
in the UI instead oftags$script(src = "js/js.cookie.js")
seems to work though.