r-spatial / rgee

Google Earth Engine for R
https://r-spatial.github.io/rgee/
Other
681 stars 146 forks source link

Error in browseURL(url): 'browser' must be a non-empty character string #141

Closed egbendito closed 2 years ago

egbendito commented 3 years ago

At submit an issue, please attached the following information of your rgee session:

Attach your Python (reticulate) configuration:

python:         /home/jovyan/.virtualenvs/rgee/bin/python
libpython:      /opt/conda/lib/libpython3.7m.so
pythonhome:     /home/jovyan/.virtualenvs/rgee:/home/jovyan/.virtualenvs/rgee
version:        3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20)  [GCC 7.3.0]
numpy:          /home/jovyan/.virtualenvs/rgee/lib/python3.7/site-packages/numpy
numpy_version:  1.20.1
ee:             /home/jovyan/.virtualenvs/rgee/lib/python3.7/site-packages/ee

NOTE: Python version was forced by RETICULATE_PYTHON

Description

Trying to initialize rgee in a non-GUI environment (no browser installed) without root permissions. Installation goes smoothly. When trying to link GEE account through OAuth using ee_Initialize() I get an error because no browser is available. getOption("browser") returns an empty string.

What I Did

library(rgee)
ee_Initialize()

Traceback:

Error in browseURL(url): 'browser' must be a non-empty character string
Traceback:

1. ee_Initialize()
2. ee_create_credentials_earthengine(email_clean, display = display)
3. ee_save_eecredentials(url = earthengine_auth, code_verifier = code_verifier, 
 .     main_ee_credential = main_ee_credential, user_ee_credential = user_ee_credential)
4. browseURL(url)
5. stop("'browser' must be a non-empty character string")
csaybar commented 3 years ago

Hi @egbendito this is possible but not secure. The idea is copy your Google Earth Engine credentials available on this folder.

library(rgee)

oauth_func_path <- system.file("python/ee_utils.py", package = "rgee")
utils_py <- rgee:::ee_source_python(oauth_func_path)

# first step
ee_path <- ee_utils_py_to_r(utils_py$ee_path())
print(ee_path)
# [1] "/home/csaybar/.config/earthengine/"

You can use other computer (with GUI) to download the credentials, after that save the credentials in, for instance, Google Drive and using Curl download/save the credentials to your system with non-GUI. But remember if someone have access to your EE credentials they will be able to use your Google Earth Engine resources.

egbendito commented 3 years ago

Hi @csaybar thanks for the reply! I was wondering if you know whether it is possible to emulate this method using the Python API for Google Earth Engine.

I have not found a way to print hyperlinks to the R console, but maybe something like below in ee_create_credentials_earthengine() line 308

if (display) {
  message("\n To authorize access needed by Earth Engine, open the following URL in a web browser and follow the instructions: \n \n", earthengine_auth, "\n \n The authorization workflow will generate a code, which you should paste in the box below")
  auth_code <- readline("Enter Earth Engine Authentication: ")
  token <- ee$oauth$request_token(auth_code, code_verifier)
  credential <- sprintf('{"refresh_token":"%s"}', token)
  write(credential, main_ee_credential)
  write(credential, user_ee_credential)
}

That way may be possible to allow the user to manually introduce the verification code and store it in the system?

I think this way it keeps most of the current structure of ee_create_credentials_earthengine() but allowing users to introduce the tokens manually (as done in the GEE Python API) using the display argument.

csaybar commented 3 years ago

Thanks @egbendito you right I think currently this part is only friendly with Rstudio and users with GUI, we will make some changes in the next release of rgee to suport colab and Rbase users. You can display the verification link as follow:

library(rgee)

oauth_func_path <- system.file("python/ee_utils.py", package = "rgee")
utils_py <- rgee:::ee_source_python(oauth_func_path)

oauth_codes <- ee_utils_py_to_r(utils_py$create_codes())
code_verifier <- oauth_codes[[1]]
code_challenge <- oauth_codes[[2]]
earthengine_auth <- ee$oauth$get_authorization_url(code_challenge)
earthengine_auth
egbendito commented 3 years ago

Great! Sounds like a good solution for authentification in non-GUI remote servers. I am trying to get it to work on a case like this.

I was reading on the gargle package, and indeed in fully non-interactive contexts your solution above is the recommended one.

Will get back to you with some tests!

Thanks @csaybar !

egbendito commented 3 years ago

Using the above code into ee_Initialize() line 307, I managed to save and store the credentials interactively in a non-GUI remote server. It could be a solution(?).

Moving on, I realized that linking GDrive is also linked using googledrive::drive_auth() which again requires a GUI browser. In this case, I am not sure how to proceed. Any suggestions?

For the GCS solution here it works like a charm! Thanks again!

csaybar commented 3 years ago

Hi @egbendito, this is a common problem in Docker environments. I think the easiest way is to copy manually all your credentials to the path:

library(rgee)

oauth_func_path <- system.file("python/ee_utils.py", package = "rgee")
utils_py <- rgee:::ee_source_python(oauth_func_path)

# first step
ee_path <- ee_utils_py_to_r(utils_py$ee_path())
print(ee_path)
# [1] "/home/csaybar/.config/earthengine/"

GEE and Google Drive use a previous OAuth2 authorization to get the respective credentials (token). However if you have your credentials somewhere you can just copy in the path above. and rgee or the earthengine-api will work. Does it have sense?. See how rgee docker container already works.

https://github.com/csaybar/rgee-docker/blob/2aaf780c51ceec70ec42cda936cc7b7cbadaa3d5/docker-compose.yml#L7