I have a shiny application that requires user to login to access the underlying dataset.
The username and password are collected from form fields and submitted via a RESTful API on another server to get an access token which is used in future requests. I haven't included those details in this example.
I want to get the web browser to remember the login details and login automatically, but can't quite see how.
In my first implementation, the <input type="text" name="username">
and <input type="password" name="password">
plus an actionButton
were dynamically added to the page. This forced the user to re-login each time the shiny application was restarted, which was complex for development and unpleasant for users.
I then found https://gist.github.com/kostiklv/968927 which details the conditions for having the web browser remember the password and log in.
Shiny works on one page, so I couldn't have a separate login page (this would generate a new shiny session, discarding the login!).
I have tried various combinations of things, here is the closest I have got. This script correctly fills in a past password, but the user still has to manually hit submit.
Note that I have a custom hack my shiny in to enable type="password"
to be treated the same as type="text"
. See bottom of question for access to this code
save this code as login.R
then run R
and type source("login.R")
write("","blank.html") require(shiny) addResourcePath("login",tools:::file_path_as_absolute("./")) runApp(list( ui=bootstrapPage( tags$form(action="#",target="loginframe", tags$input(id="username",type="text",placeholder="Username"), tags$input(id="password",type="password",placeholder="Password"), tags$input(id="loginButton",class="btn btn-primary",type="submit",value="Login") ), tags$iframe(name="loginframe",src="login/blank.html",style="display:none") ), server=function(input, output) { observe({message( "username ",input$username,"\n", "password ",input$password,"\n" )}) }) )
Note that the presence of an html input submit button
seems to tell shiny that it should only update the inputs once every submit. Without the submit button shiny updates its inputs every keystroke.
The same is true for shiny's submitButton
.
Leaving the form but removing the button allows input$username and input$password to reach the server code, but...
To enable both conventional user login and automated login, I need the button to avoid repeated attempts to authenticate (which might cause problems) for partial usernames and passwords.
Here are the console logs from the tests
username password <enter username AA and password BB> *no update* <hit submit> *browser requests to save password / yes* username A password B <refresh page> username password * onscreen form inputs are populated * <hit submit> username A password B
Comment out tags$input(id="loginButton",class="btn btn-primary",type="submit",value="Login") and the preceding comma
note you may want to tell your browser to forget localhost web passwords for now.
username password <enter username AA and password BB> username A password username AA password username AA password B password BB <refresh browser> * onscreen form inputs are not populated * * browser requests to save password * username password <refresh browser> * onscreen form inputs are populated * username password username AA username BB
Install using library(devtools)
install_github("shiny","alexbbrown",ref="password-field")
Or download and install manually:
https://github.com/alexbbrown/shiny.git (branch password-field)
Or patch your shiny manually:
index 9b63c7b..15377d8 100644 --- a/inst/www/shared/shiny.js +++ b/inst/www/shared/shiny.js @@ -1336,7 +1336,7 @@ var textInputBinding = new InputBinding(); $.extend(textInputBinding, { find: function(scope) { - return $(scope).find('input[type="text"]'); + return $(scope).find('input[type="text"],input[type="password"]'); }, getId: function(el) { return InputBinding.prototype.getId.call(this, el) || el.name;
cf Password field using R Shiny framework
Manual steps to build authentication page. Username : myuser Password : mypass Username : myuser1 Password : mypass1 . To change them, you can edit the following code in R program. In order to modify sidebar section, you can edit the following section of code.
I was looking for something similar, and trestletech's fantastic package shinyStore
worked for me.
It enables HTML5 client-side data storage for any data in your shiny app.
The github page is here, and an example of how it works is here.
You may wish to read the "Security" section on the README and ensure it is secure enough for your purposes.
I believe that you can use postForm()
from RCurl
package to perform a regular HTTP form submit request (unless Shiny
would interfere with this functionality, which is based on using underlying libcurl
library). For an example code, please see function srdaLogin()
in my R module "getSourceForgeData.R": https://github.com/abnova/diss-floss/blob/master/import/getSourceForgeData.R.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With