If you have ever received an embarrassing message with a warning saying that you may have published your credentials or secrets when publishing your code, you know what I’m talking about. A very common mistake among noob coders is (temporarily) hardcoding passwords, tokens, secrets, that should never be shared with others, and… shared them.

Today I’ll share with you a simple but effective approach.

I have several functions that live in my public lares library that use get_creds() to fetch my secrets. Some of them are used as credentials to query databases, send emails with API services such as Mailgun, ping notifications using Slack‘s webhook, interacting with Google Sheets programatically, fetching Facebook and Twitter’s API stuff, Typeform, Github, Hubspot… I even have a portfolio performance report for my personal investments. If you check the code underneath, you won’t find credentials written anywhere but the code will actually work (for me and for anyone that uses the library). So, how can we accomplish this?

You may want to install the library to follow the examples:

install.packages("lares")

Credentials in YAML files

A YAML (acronym for “YAML Ain’t Markup Language”) file is a readable text file, commonly used to save configurations in a .yml file. So, the trick here will be to post our credentials and secrets into a local YAML file, set RStudio to “know and remember” where it is saved, and call the file every time we use a credential-needed-function. That’s where get_creds comes in!

When using functions in lares that need credentials to actually work, you’ll notice there is always a creds argument. In it, you’ll specify which service you need to fetch the secrets from and will be used in the function. Every time you call this function it will check for your .Renviron file which will reveal where you have your .yml file is and get a list with the credentials needed.

The first time you run the get_creds() or use any function that has the creds parameter, it will reactively ask you to set the path for tour YAML local file. This will be asked once and will be set for further R sessions. Remember, once you change this path you must reset your session for this setup to start working properly.

One-time only setup

Let’s run an example. If you already have a YAML file, you’re halfway there. If you already installed the lares library, you already have a dummy file locally that will work just fine for this exercise; you can find it here: system.file("docs", "config.yml", package = "lares"). If not, you can download the file and save it in your machine, wherever you wish to keep it.

1. Know the path: you must place the YAML file in a secure place and know its absolute path.

2. Set the path: load the library and call the get_creds() function to set the directory. It will ask for the directory (not the file).

library(lares)
# I'm using this function to get the library's dummy file directory
# dirname(system.file("docs", "config.yml", package = "lares"))
get_creds()
Please, set your creds directory (one-time only step to set LARES_CREDS):
Set directory where your config.yml file is saved: 

/Library/Frameworks/R.framework/Versions/4.0/Resources/library/lares/docs
ALL's SET! But, you must reset your session for it to work!

3. Reset your session: close your R/RStudio session and open it again. That should be all!

get_creds()
NULL
Warning message:
In get_creds() : No credentials for NA found in your YML file. 
Try any of the following: 'service1', 'service2', 'service3'

We did it! As the warning message suggested, we can run the same function with one of the options available in our file. We’ll get a “list” object containing a (dummy) username, a repo, and a (fake) token, which can be now passed to any function without revealing its values. Awesome, right!?

get_creds("service3")
$username
[1] "myusername"

$repo
[1] "laresbernardo/lares"

$token
[1] "clntbjnrdbgvutdlkcecricuurtjtnbe"

Once you set your path, it will work from now on as long as you keep your file in the correct path. Of course, you don’t need the library to follow this logic, but feel free to use it and pass any feedback. I’ve been using this method for more than 3 years now, locally and in servers, with no issues so far.

BONUS 1: I frequently use 2-3 different computers all the time. To avoid having three different files (which will probably be recommended for security reasons), I only have one that syncs across all machines using Dropbox. So the path I’ve set is ~/Dropbox (Personal)/... for all of them, regardless of their origin path names.

BONUS 2: You can manually change your .Renviron file with usethis::edit_r_environ(). Even though you could add all your credentials directly into this file, I’d rather use this post’s function because you can sync/share/admin a file to be used in several computers, you can group credentials by services and use them as lists, it has a warning that shows available services if you ask for the wrong (or none) service name, and I find it way friendlier.

Hope you find this approach useful next time you are in need of hiding your coding secrets! Reveal only what’s necessary and avoid shouting your credentials out to the web.

“Keep it secret, keep it safe” _Gandalf, the Grey

Happy coding!