Does R have a function that allows a user to provide a password securely, such as Python's getpass
module?
(see http://docs.python.org/library/getpass.html for an example of what I mean)
Does R have a function that allows a user to provide a password securely, such as Python's getpass
module?
(see http://docs.python.org/library/getpass.html for an example of what I mean)
The problem is that R does not have functions to control the terminal it is running in (something like Rncurses
); probably this is due to portability issues.
Some time ago I was struggling with the same problem and I ended up with a function using TclTk:
getPass<-function(){
require(tcltk);
wnd<-tktoplevel();tclVar("")->passVar;
#Label
tkgrid(tklabel(wnd,text="Enter password:"));
#Password box
tkgrid(tkentry(wnd,textvariable=passVar,show="*")->passBox);
#Hitting return will also submit password
tkbind(passBox,"<Return>",function() tkdestroy(wnd));
#OK button
tkgrid(tkbutton(wnd,text="OK",command=function() tkdestroy(wnd)));
#Wait for user to click OK
tkwait.window(wnd);
password<-tclvalue(passVar);
return(password);
}
Of course it won't work in non-GUI environments.
Very simple linux concept for terminal secure password question:
password <- function(prompt = "Password:"){
cat(prompt)
pass <- system('stty -echo && read ff && stty echo && echo $ff && ff=""',
intern=TRUE)
cat('\n')
invisible(pass)
}
My package keyringr solves this problem by retrieving passwords from the underlying operating system keyring (DPAPI on Windows, Keychain on OSX and the Gnome Keyring on Linux).
The vignette gives a detailed explanation on how to use the package, but if you were using OSX and have the password saved in Keychain, you could use the following command to return the password to R (where mydb_myuser is the Keychain item name):
install.packages("keyringr")
library("keyringr")
mypwd <- decrypt_kc_pw("mydb_myuser")
print(mypwd)
Per m-dz in the comments above, there is a now a package for doing this called getPass, which has a single function, getPass()
. This is a replacement for base::readline()
.
Here is a login pop-up, based on ?modalDialog.
library("shiny")
shinyApp(
ui <- basicPage(
actionButton("login", "Login"),
verbatimTextOutput("secrets")
),
server <- function(input, output, session) {
vals <- reactiveValues(authenticated=FALSE)
passwordModal <- function(message=NULL) {
modalDialog(
textInput("username", "Username", input$username),
passwordInput("password", "Password", input$password),
if (!is.null(message)) div(tags$b(message, style="color: red;")),
footer = tagList(
modalButton("Cancel"),
actionButton("authenticate", "OK")
)
)
}
observeEvent(input$login, {
showModal(passwordModal())
})
observeEvent(input$authenticate, {
vals$authenticated <- FALSE
if (!is.null(input$username) && nzchar(input$username) &&
!is.null(input$password) && nzchar(input$password)) {
removeModal()
if (input$password == "letmein") {
vals$authenticated <- TRUE
} else {
showModal(passwordModal(message="Incorrect password!"))
}
} else {
showModal(passwordModal(message="Please fill in your username and password"))
}
})
output$secrets <- renderText({
if (vals$authenticated) {
paste("Don't tell anyone, ", input$username, ", but...", sep="")
} else {
"I can't tell you that!"
}
})
}
)