Unlock R functions with QR codes


November 1, 2023

Screenshot of the computer from Jurassic Park with repeating monospace text in all caps saying 'you didn't say the magic word' and a photo of the antagonist's (Nedry's) head on a cartoon body wagging his finger.

Uh uh uh! (Jurassic Park via BJ22CS)


What if (hear me out) you could prevent an R function from operating correctly unless the user presents a specific QR code?

QR you?

Jeroen announced that the latest version of the {opencv} package is capable of detecting and decoding a QR code.

So this means we could write a function that only returns an answer when you introduce a QR code that encodes the correct ‘password’.

add_one <- function(n) {
  string_in <- opencv::qr_scanner()
  password <- RCurl::base64Decode("b3BlbmN2IHNlc2FtZSE=")
  if (string_in == password) {
    cat("🔑 Correct password!\n")
    n + 1
  } else {
    stop("Wrong password!", call. = FALSE)

So add_one() uses the qr_scanner() function to find and read a QR code from a video image and compare that to a password before giving the answer. You can see in the function body that I’ve only mildly obfuscated the password, using base64 encoding. Maybe you can do something more secure?

Now to run the function:

Starting video window (could be behind this window)

This will activate your device’s camera and it will keep looking for a QR code before it runs the rest of the code in the function.

The ‘correct’ QR code (made with {qrcode}) is this one:

A QR code.

Maybe this is a rickroll, who knows?

If you then scan this QR code with your device you’ll get an answer:

Correct password!
[1] 2

Here’s a gif of the process:

Screengrab gif. An R function called 'add_one' is run in the terminal with the argument '1'. A message is printed saying 'Starting video window (could be behind this window)' and then a video image appears, showing the corner of a room. A phone displaying a QR code flashes briefly in front of the screen. The Terminal window returns and the message 'correct password' is displayed, along with the answer value of '2'.

Halloween special: the QR code appears like a jumpscare

The add_one() function was run, my laptop’s camera opened and then I showed it the QR code on my phone. The code was detected super quickly and the correct answer was returned in the console.

I think there’s a lot of promise in this approach for helping to monetise your R package!


As Jeroen and Dan pointed out: you could use this to create an R-based multi-factor authentication solution by introducing {otp} and {ntfy} into the mix.

I also wanted to mention Tom’s talk at the recent NHS-R conference. Tom had fun building a conference check-in service with personalised QR codes, making use of {plumber} and {blastula} in the back end.


Session info
Last rendered: 2023-11-01 10:23:17 GMT
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.2.1

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0

[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: Europe/London
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] htmlwidgets_1.6.2 compiler_4.3.1    fastmap_1.1.1     cli_3.6.1        
 [5] tools_4.3.1       htmltools_0.5.6.1 rstudioapi_0.15.0 yaml_2.3.7       
 [9] rmarkdown_2.25    knitr_1.44        jsonlite_1.8.7    xfun_0.40        
[13] digest_0.6.33     rlang_1.1.1       fontawesome_0.5.2 evaluate_0.22