library(meetupr)

API key? No

As of August 15, 2019, Meetup.com switched from an API key based authentication system to OAuth 2.0, so we added support for OAuth.

OAuth? Yes

Meetup API and this package recommend using OAuth for authentication. We’ve abstracted part of the difficulty but it’s still a bit more complex than storing a simple API key as secret.

With OAuth you need

  • an OAuth app. There’s one shipped in with the package! If you prefer you can bring your own app by setting the meetupr.consumer_key and meetupr.consumer_secret options.

  • an access token. It’s an httr object and it can be saved to disk. It expires but can be refreshed. It contains secrets so it’s a sensitive file! For creating one you will be prompted to log into your meetup.com account in the browser. But then if you cache the token to disk, you won’t need to do that again. This means you can create a token on your computer locally and use it on a server (if the server is public, encrypting the token).

Let’s go through workflows and ways to control how your token is created and cached.

If you don’t tweak anything, the first time you run a meetupr function, you’ll be prompted to go into your browser and a token will be created. It will be saved to disk in an app directory as determined by rappdirs::user_data_dir("meetupr", "meetupr")

And all the times you use meetupr again, this token will be used, and refreshed and re-saved as needed.

This is, we hope, a sensible default.

Now if you want to have a different behavior you either tweak options (in your .Rprofile so for all sessions in the future, or just in the current session), or call the meetup_auth() function directly.

  • Don’t want to cache the token to disk? Use the cache argument, to be set to FALSE.
  • Don’t want to use an app dir? Use the use_appdir argument, to be set to FALSE. If it is false, the token will be cached to .httr-oauth (unless cache is FALSE too, of course)
  • Want to save the token to somewhere you choose? No way to use an option. Use the token_path argument of meetup_auth().
  • Want to use a token that was created elsewhere? Save it to disk, keep it secret, and refer to it via the token argument of meetup_auth() that can be either a token or the path to a token.

What about running my code on a server

Please read httr vignette about secrets and gargle vignette about managing tokens securely.

Here is how we handle our secret token for testing the package, it might inspire you.

Create and encrypt the token

First we create a token. We build and git ignore it, even safer would be to put it elsewhere on the computer, maybe a temporary file!

token_path <- testthat::test_path(".meetup_token.rds")
use_build_ignore(token_path)
use_git_ignore(token_path)

meetupr::meetup_auth(
  token = NULL,
  cache = TRUE,
  use_appdir = FALSE,
  token_path = token_path
)

We create a key and save it as an environment variable. We used an internal function for saving it, you could copy-paste it to .Renviron by hand (see also usethis::edit_r_environ()).

# sodium_key <- sodium::keygen()
# save an environment variable "MEETUPR_PWD" = sodium::bin2hex(sodium_key)

Using the key we encrypt the file. secret.rds will be committed to our repo!

key <- cyphr::key_sodium(sodium::hex2bin(Sys.getenv("MEETUPR_PWD")))

cyphr::encrypt_file(
  token_path,
  key = key,
  dest = testthat::test_path("secret.rds")
)

Use the token on CI

  • Save the MEETUPR_PWD environment variable as secret on CI (actually called repo secret for e.g. GitHub Actions)

  • Use the code below to decrypt the secret before using meetupr. We save the temporary token to disk but to a temporary folder so it won’t end up in a package check artefact.

key <- cyphr::key_sodium(sodium::hex2bin(Sys.getenv("MEETUPR_PWD")))

temptoken <- tempfile(fileext = ".rds")

cyphr::decrypt_file(
  testthat::test_path("secret.rds"),
  key = key,
  dest = temptoken
)

token <- readRDS(temptoken)[[1]]

token <- meetupr::meetup_auth(
  token = token,
  use_appdir = FALSE,
  cache = FALSE
)

Sys.setenv(MEETUPR_PAT = temptoken)