Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: parse error: premature EOF from gs4_auth_configure() #260

Closed
moldach opened this issue Jun 17, 2022 · 17 comments
Closed

Error: parse error: premature EOF from gs4_auth_configure() #260

moldach opened this issue Jun 17, 2022 · 17 comments

Comments

@moldach
Copy link

moldach commented Jun 17, 2022

From Google Cloud Platform I create credentials for OAuth 2.0 Client and it says:

Your Client ID: XXXXX
Your Client Secret: XXXXX
Download JSON

I've downloaded the JSON file and attempt to set up authorization but I get a premature EOF error

> library(googlesheets4)
> app_path <- system.file(
+     "extdata", "client_secret_581966527550-10nsh36iuvi4eoacp58tmnmsrn4m3mms.apps.googleusercontent.com.json",
+     package = "googlesheets4"
+ )
> gs4_auth_configure(path = app_path)
Error: parse error: premature EOF
                                       
                     (right here) ------^
> 
@jennybc
Copy link
Member

jennybc commented Jun 17, 2022

Your JSON file is not going to be found inside the googlesheets4 installation, which is what you're claiming above. Why are you using system.file(..., package = "googlesheets4")?

@moldach
Copy link
Author

moldach commented Jun 17, 2022

Same error:

> app_path <- system.file("client_secret_581966527550-10nsh36iuvi4eoacp58tmnmsrn4m3mms.apps.googleusercontent.com.json")
> gs4_auth_configure(path = app_path)
Error: parse error: premature EOF
                                       
                     (right here) ------^

@jennybc
Copy link
Member

jennybc commented Jun 17, 2022

Why are you using system.file() at all?

@moldach
Copy link
Author

moldach commented Jun 17, 2022

Honestly the documentation for connecting via a server is a bit lacking and I'm struggling to make this work

@moldach
Copy link
Author

moldach commented Jun 17, 2022

When I type ?gs4_oauth_app() I saw the following:

# bring your own app via JSON downloaded from Google Developers Console
       # this file has the same structure as the JSON from Google
       app_path <- system.file(
         "extdata", "fake-oauth-client-id-and-secret.json",
         package = "googlesheets4"
       )
       gs4_auth_configure(path = app_path)
       

So I just tried that.

When I supply the direct path:

gs4_auth_configure(path="client_secret_581966527550-10nsh36iuvi4eoacp58tmnmsrn4m3mms.apps.googleusercontent.com.json")


> read_sheet('https://docs.google.com/spreadsheets/d/1sSsZq-4bNP5pzqpgBBsKwFgs9l83G-AMuFuqSXeeQzs/edit#gid=2086882649')
Error in `gargle_abort_request_failed()`:
! Client error: (403) PERMISSION_DENIED
• Client does not have sufficient permission. This can happen because the OAuth token does not have the right scopes, the
  client doesn't have permission, or the API has not been enabled for the client project.
• The caller does not have permission
Run `rlang::last_error()` to see where the error occurred.

How can I trouble shoot this?

@moldach
Copy link
Author

moldach commented Jun 17, 2022

Okay, so I created a service account on GCP then enabled API access to Google Sheets.
Next, I granted access to that e-mail account on my google spreadsheet.

Then, I create both an API Key as well as a OAuth 2.0Client ID

Screen Shot 2022-06-17 at 3 45 49 PM



> google_app <- httr::oauth_app(
+   "test",
+   key = "MY-KEY.apps.googleusercontent.com",
+   secret = "MY-SECRET"
+ )
> google_key="MY-API-KEY"
> gs4_auth_configure(app = google_app, api_key = google_key)
> gs4_oauth_app()
<oauth_app> test
  key:    MY-KEY.apps.googleusercontent.com
  secret: <hidden>
>   gs4_api_key()
[1] "MY-API-KEY"
> read_sheet("https://docs.google.com/spreadsheets/d/1ZW6kuA-80BRXV0gdoqU_5M4NLp4yMAH3mINgZFBQBFE/edit#gid=833357056")
Error in `gargle_abort_request_failed()`:
! Client error: (403) PERMISSION_DENIED
• Client does not have sufficient permission. This can happen
  because the OAuth token does not have the right scopes, the client
  doesn't have permission, or the API has not been enabled for the
  client project.
• The caller does not have permission
Run `rlang::last_error()` to see where the error occurred.

Also getting an error here?

Under the GCP Permissions I can see that my personal e-mail is set as a PRINCIPALS to this service account so I'm not sure what's wrong...

@jennybc
Copy link
Member

jennybc commented Jun 20, 2022

You seem to be configuring 3 different auth methods (oauth user flow, API key, service account token), when I suspect you only need to want 1. It feels pretty confused.

When you get permission denied, who are you auth'ed as? Yourself or the service account?

googlesheets4::gs4_user() will reveal the user whose token is currently in force for googlesheets4.

@moldach
Copy link
Author

moldach commented Jun 20, 2022

Okay let's just try one method then from a fresh console. I will also create new credentials on GCP for OAuth client ID (Application Type: Desktop APP, name: test2) which allows me to download a JSON file client_secret_581966527550-qh88161edonl1hh0vj6elrpe48p72i4i.apps.googleusercontent.com.json.

If I do the following, it shows me that there is no current user?

> library(googlesheets4)
> gs4_auth_configure(path="client_secret_581966527550-qh88161edonl1hh0vj6elrpe48p72i4i.apps.googleusercontent.com.json")
> googlesheets4::gs4_user()
ℹ Not logged in as any specific Google user.

However, using gs4_oauth_app() I see:

> gs4_oauth_app()
<oauth_app> tgi-data-ingest
  key:    581966527550-qh88161edonl1hh0vj6elrpe48p72i4i.apps.googleusercontent.com
  secret: <hidden>
> 

@jennybc
Copy link
Member

jennybc commented Jun 20, 2022

googlesheets4 does not load a token until one is needed. So you need to do something that requires auth or trigger auth explicitly with gs4_auth().

An OAuth app is one part of the machinery needed for a user to complete the process known as "three-legged oauth". Configuring the app does not actually obtain a token on behalf of any particular authenticated user.

@jennybc
Copy link
Member

jennybc commented Jun 20, 2022

@moldach
Copy link
Author

moldach commented Jun 20, 2022

trigger auth explicitly with gs4_auth().

You can not do this on Servers though....

> gs4_auth()
Waiting for authentication in browser...
Press Esc/Ctrl + C to abort
/usr/bin/xdg-open: 869: www-browser: not found
/usr/bin/xdg-open: 869: links2: not found
/usr/bin/xdg-open: 869: elinks: not found
/usr/bin/xdg-open: 869: links: not found
/usr/bin/xdg-open: 869: lynx: not found
/usr/bin/xdg-open: 869: w3m: not found
xdg-open: no method available for opening 'https://accounts.google.com/o/oauth2/auth?client_id=603366585132-dpeg5tt0et3go5of2374d83ifevk5086.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&redirect_uri=http%3A%2F%2Flocalhost%3A1410%2F&response_type=code&state=X2VfKk7xkj'

So you need to do something that requires auth

Can you please provide code to be more clear in what I need to do?

The link you shared has those exact steps I just described for creating my OAUth Client ID above:

  • From the Developers Console, in the target GCP Project, go to APIs & Services > Credentials.
  • Do Create credentials > OAuth client ID.
  • Select Application type “Desktop app”.
  • You can capture the client ID and secret via clipboard right away.
  • At any time, you can navigate to a particular client ID and click “Download JSON”.**

This was followed by me using gs4_auth_configure (which I thought you need to use if you cannot use gs4_auth?)

> gs4_auth_configure(path="client_secret_581966527550-qh88161edonl1hh0vj6elrpe48p72i4i.apps.googleusercontent.com.json")

So what step am I missing? How to I tell googlesheets4 my email address on a server?

@jennybc
Copy link
Member

jennybc commented Jun 22, 2022

Google has shut down out-of-band auth for newly obtained OAuth apps which, presumably, includes yours. No real replacement is offered for our use case, sadly.

r-lib/gargle#202

The tidyverse oauth app which ships with googlesheets4 is grandfathered in, for a limited period of time, and can still be used for OOB auth.

So if you want to auth with a user token, via R/RStudio on a server, you have two options:

  1. Use the built-in app, not your own oauth app, to get the token.
  2. Create an oauth token locally (meaning: not on a server) with your oauth app and move/deploy it to the server (where it can still be used and refreshed).

The process of deploying a locally obtained token to a server is described here:

https://gargle.r-lib.org/articles/non-interactive-auth.html#arrange-for-an-oauth-token-to-be-re-discovered

@moldach
Copy link
Author

moldach commented Jun 22, 2022

Hi @jennybc, thanks for sharing link to option 2 there.

After creating the token locally and SCP it to the server it seems to work for the googledrive package:

> library(googledrive)
> 
> options(
+   gargle_oauth_cache = ".secrets",
+   gargle_oauth_email = TRUE
+ )
> 
> # now use googledrive with no need for explicit auth
> drive_find(n_max = 5)
ℹ The googledrive package is using a cached token for
  matthew.oldach@contractors.roche.com.
# A dribble: 5 × 3
  name                                id                          drive_resource
  <chr>                               <drv_id>                    <list>        
1 TGI ecosystem                       13yEffuvixdceOHlyIC1YAKlR4… <named list>  
2 Development priorities GERMLINE/TGi 1L41ewezJ1N-UyG9Fttgn073Jn… <named list>  
3 GERMLINE ecosystem                  17Rez4dCiktzt2fzAb-9rOXvEr… <named list>  
4 Failure Mode and Effects Analysis   1ouE1JGZzAYm0nJDe2sPhN4584… <named list>  
5 CI/CD sync (2022-06-21 10:03 GMT-7) 1n2tPzqMW-hZJHxv1oNUWDNaf6… <named list> 

However, I'm still getting an error from googlesheets4:

> read_sheet("https://docs.google.com/spreadsheets/d/1ZW6kuA-80BRXV0gdoqU_5M4NLp4yMAH3mINgZFBQBFE/edit#gid=833357056")
The httpuv package enables a nicer Google auth experience, in many cases.
It doesn't seem to be installed.
Would you like to install it now?

1: Yes
2: No

Selection: 2
httpuv not installed, defaulting to out-of-band authentication
Enter authorization code: /usr/bin/xdg-open: 869: www-browser: not found
/usr/bin/xdg-open: 869: links2: not found
/usr/bin/xdg-open: 869: elinks: not found
/usr/bin/xdg-open: 869: links: not found
/usr/bin/xdg-open: 869: lynx: not found
/usr/bin/xdg-open: 869: w3m: not found
xdg-open: no method available for opening 'https://accounts.google.com/o/oauth2/auth?client_id=603366585132-dpeg5tt0et3go5of2374d83ifevk5086.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code'

Any idea what else am I missing here?

Note: Additional issue is that I see aboveGoogleDrive is only showing 5 documents which were created by me; I do not see the document which trying to access. For this document I want to access with read_sheet my role is Editor - do you need to be the Owner?

@jennybc
Copy link
Member

jennybc commented Jun 23, 2022

Hard to say since I'm clearly not seeing all of the code.

Or maybe I am? In which case I can say for sure that you need to explicitly tell googlesheets4 to use the same token as googledrive is using:

https://googlesheets4.tidyverse.org/articles/drive-and-sheets.html

It won't automatically do so.

@moldach
Copy link
Author

moldach commented Jun 23, 2022

Hi @jennybc the critical part I was missing was telling googlesheet4 to use the same token as googledrive:

> options(gargle_oauth_cache = "~/.secrets", gargle_oauth_email=TRUE)
# missing line
> gs4_auth(token = drive_token())

Thank you very much!

@moldach moldach closed this as completed Jun 23, 2022
@NicoleRadziwill
Copy link

Giant thanks to Matthew Oldach (moldach) for asking these questions 1.75 years ago. I've been trying to deploy a Plumber API on AWS the past week, and the part I was missing was telling gs4 to use the same token as googledrive. In particular, this is how this solution worked for me (and I've tried taking out pieces of this one, so some how some way, all the pieces in this are needed):

   googledrive::drive_auth(path = "my-service-account-download-from-GCP.json") 
   googlesheets4::gs4_auth(token = drive_token())
   googlesheets4::gs4_auth(path = "my-service-account-download-from-GCP.json") 

@jennybc
Copy link
Member

jennybc commented Mar 20, 2024

The two googlesheets4::gs4_auth() calls don't make sense to me. I would suggest lines 1 and 3:

googledrive::drive_auth(path = "my-service-account-download-from-GCP.json") 
googlesheets4::gs4_auth(path = "my-service-account-download-from-GCP.json")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants