Skip to content

Instantly share code, notes, and snippets.

@calligross
Last active August 23, 2023 17:22
Show Gist options
  • Save calligross/e779281b500eb93ee9e42e4d72448189 to your computer and use it in GitHub Desktop.
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.
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)
@TomWeishaar
Copy link

Not only did you show me how to do logins, you introduced me to the Shinyjs package, which has been extremely helpful. Bravo!

@xwydq
Copy link

xwydq commented Sep 27, 2017

nice!!! man

@Gh0stSG1
Copy link

Gh0stSG1 commented Jun 2, 2019

Nice work!

In line 10 you set the destination file as: 'js.cookies.js' with:
"destfile = 'www/js.cookies.js'"

In the ui you load the file as "js.cookie.js" (without the s.... cookie instead of cookies). This breaks the example.

@calligross
Copy link
Author

Thanks, I fixed it.

@markusdumke
Copy link

'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 of tags$script(src = "js/js.cookie.js") seems to work though.

@calligross
Copy link
Author

Using tags$script(src = "https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js") in the UI instead of tags$script(src = "js/js.cookie.js") seems to work though.

Thanks, I updated the download URL.

@gituser945
Copy link

gituser945 commented Dec 2, 2019

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'

@FarhanShahJahan
Copy link

FarhanShahJahan commented Dec 18, 2020

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