You cannot use the 3-legged variant of OAuth2.0 (aka "web-application flow") in a headless environment like Github Actions.
If you want to use OAuth (I list other possibilities below), then you need to utilize what gitlab calls the "device-flow". See github documentation.
In this flow, there is no redirect to a given URL, so the app does not need a browser window. Instead it displays a code to the user. The user must the enter that code on a fixed URL (https://github.com/login/device). As soon as this is done, the app can request the authentication token. (So the app must keep polling until the user has entered the code).
Unfortunately, httr
does not have nice wrapper functions for this variant, so you have to do the calls yourself. It can work like this:
library(httr)
app_id <- "*redacted*"
r <- POST("https://github.com/login/device/code",
body = list(
client_id = app_id,
scope = "user repo delete_repo" #Scope must be given! https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
))
device_code <- content(r)$device_code
print(paste0("Enter the code ", content(r)$user_code, " at ", content(r)$verification_uri))
## NOTE: In reality this request has to run in a loop, until the user has entered the code und the request succeeds.
## For the demo we can execute it manually after the code has been entered.
r <- POST("https://github.com/login/oauth/access_token",
body = list(
client_id = app_id,
device_code = device_code,
grant_type = "urn:ietf:params:oauth:grant-type:device_code"
))
token <- content(r)$access_token
## create and delete a private testrepository to check if everything worked
r <-
POST("https://api.github.com/user/repos",
add_headers(Authorization = paste("token", token)),
body = list(name = "testrepo",
private = TRUE,
auto_init = FALSE),
encode = "json")
r <- DELETE(paste0("https://api.github.com/repos/", content(r)$full_name),
add_headers(Authorization = paste("token", token)))
I have seen that there is httr2
, and that it offers convenience functions for this flow. I have however never used it and do not know if it already works reliable. See here.
Since this flow still requires user interaction, you may be better of with one of the following variants (I do not know if they fit your use case.):
Basic Auth:
You can define what github calls a "personal access token" beforehand. With this token you can authenticate without further interaction. Creation is described here. In R you can use it most easily together with httr::authenticate
.
GITHUB_TOKEN:
Github automatically creates special secrets specifically Github Actions. These can be used to execute actions in the containing repository. For more info see here.