MarkEdmondson1234 / googleAuthR

Google API Client Library for R. Easy authentication and help to build Google API R libraries with OAuth2. Shiny compatible.
https://code.markedmondson.me/googleAuthR
Other
175 stars 51 forks source link

gar_set_client without using json file #216

Open can-taslicukur opened 2 years ago

can-taslicukur commented 2 years ago

Currently, if i need to use gar_set_client() , I have to provide a json file. However, storing the json file in a machine may increase the probability of leaking the sensitive information in the json file. I think providing the contents of the json file as an argument to gar_set_client is better since i can use environment variables.

When i read the documentation of the gar_set_client, it says

This function helps set the options(googleAuthR.client_id), options(googleAuthR.client_secret) and options(googleAuthR.scopes.selected) for you. You can also set the web application client IDs that are used in Shiny authentication, that are set via the options options(googleAuthR.webapp.client_id), options(googleAuthR.webapp.client_secret)

However when i look at the source code, i've realized that it actually does more than that. Apart from setting environment variables and options, it invokes oauth_app()and gar_auth_configure() . So setting the options mentioned in the documentation is not the same thing as calling gar_set_client with a json file.

To overcome this issue in my own use case (web client used in shiny application built with docker) I have created this very ugly looking function.

library(googleAuthR)
library(httr)

# set the environment variables that will going to be used in the function
Sys.setenv("GGL_WEB_CLIENT_ID"="xXxX")
Sys.setenv("GGL_WEB_CLIENT_SECRET"="xXxX")
Sys.setenv("GGL_WEB_PROJECT_ID"="xXxX")

gar_set_client_manually <- function(scopes){

    options(googleAuthR.webapp.client_id = Sys.getenv("GGL_WEB_CLIENT_ID"), #get web client id from environment variable
            googleAuthR.webapp.client_secret = Sys.getenv("GGL_WEB_CLIENT_SECRET")) #get web client secret from environment variable

    Sys.setenv(GAR_WEB_CLIENTID = Sys.getenv("GGL_WEB_CLIENT_ID")) 
    Sys.setenv(GAR_WEB_CLIENT_SECRET = Sys.getenv("GGL_WEB_CLIENT_SECRET"))
    Sys.setenv(GAR_SCOPES = paste(scopes, collapse = ","))
    options(googleAuthR.scopes.selected = scopes)

    web_project_id <- Sys.getenv("GGL_WEB_PROJECT_ID") #get web project id from environment variable

    app <- oauth_app(paste0("web-", Sys.getenv("GGL_WEB_PROJECT_ID")), 
                     key = Sys.getenv("GGL_WEB_CLIENT_ID"), secret = Sys.getenv("GGL_WEB_CLIENT_SECRET"))
    gar_auth_configure(app = app)

    return(
        web_project_id
    )
}

With this function i am able to achieve same functionality as gar_set_client without using json file. Instead, I use GGL_WEB_CLIENT_ID, GGL_WEB_CLIENT_SECRET , GGL_WEB_PROJECT_ID environment variables.

I think adding another function that enables user to pass the contents of the json file instead of the path of the json file could be good improvement.

MarkEdmondson1234 commented 2 years ago

Ok makes sense. It was possible to do this before but was removed in favor of the client file but I found a situation myself recently where that wasn't convenient, so will look at being able to supply them directly again too, as it used to do.

predict42-patrick commented 2 years ago

We saw your solution for replacing the file paths with environment variables as its greatly increases security. We now also tried to replace the "googleAuthR::gar_auth_service()" function due the same problematic but we cannot get it working.

custom_googleAuthR_init <- function(VM_SECRET, VM_SERVICEACCOUNT){

  #googleAuthR::gar_set_client(configMtrx[,"clientsecret"])
  gar_set_client_manually()

  # googleAuthR::gar_auth_service(configMtrx[,"servicekey"])
  endpoint <- httr::oauth_endpoints("google")
  scope <- getOption("googleAuthR.scopes.selected")
  scope <- paste(scope, collapse = " ")
  google_token <- httr::oauth_service_token(endpoint=endpoint, secrets=VM_SERVICEACCOUNT, scope=scope)

  .auth$set_cred(google_token)
  .auth$set_auth_active(TRUE)
  invisible(google_token)

  return(invisible(google_token))
}

With this function we also receive an error when trying to access Google Cloud content: objects <- gcs_list_objects(configMtrx[,"cloud-bucket"]) ℹ 2021-12-21 17:48:58 > No authorization yet in this session! ℹ 2021-12-21 17:48:58 > No .httr-oauth file exists in current working directory. Do library authentication steps to provide credentials.

Do you have a solution for this step as well? As it would make the whole authentification process complete.