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

TypeError: Credentials need to be from either oauth2client or from google-auth #769

Closed
alecbw opened this issue Apr 25, 2020 · 3 comments
Closed

Comments

@alecbw
Copy link

alecbw commented Apr 25, 2020

Describe the bug
A change in version 3.4.0 broke my gspread.authorize(). I must use from_service_account_info (can't have a .json file in my environment), and rely upon this hack to enable it with a combo of google-auth and oauth2client.

To Reproduce
Steps to reproduce the behavior:

  1. pip install --force-reinstall gspread==3.3.1

  2. run the below code

  3. pip install --force-reinstall gspread==3.4.0

  4. run the below code and it breaks

This Google Colab (Jupyter notebook service) demonstrates it, as well.

Expected behavior
It should keep working? I am not clear why this is not working, but a minor version should not break my auth.

Code example

import gspread
import google.auth.transport.requests
from oauth2client.service_account import ServiceAccountCredentials
from google.oauth2 import service_account
import os

class OAuth2ServiceAccountFromGoogleOAuth2(ServiceAccountCredentials):
    def __init__(self, google_oauth2_credentials):
        self.google_oauth2_credentials = google_oauth2_credentials
        self.access_token = google_oauth2_credentials.token

    def refresh(self, http):
        if self.access_token is None:
            request = google.auth.transport.requests.Request()
            self.google_oauth2_credentials.refresh(request)
            self.access_token = self.google_oauth2_credentials.token

def open_gsheet(sheet_name):
    auth = {
        "private_key": os.environ["GSHEETS_PRIVATE_KEY"].replace("\\n", "\n").replace('"', ''),
        "client_email": os.environ["GSHEETS_CLIENT_EMAIL"],
        "token_uri": "https://oauth2.googleapis.com/token",
    }
    scopes = ['https://www.googleapis.com/auth/spreadsheets']
    credentials = service_account.Credentials.from_service_account_info(auth, scopes=scopes)
    gc = gspread.authorize(OAuth2ServiceAccountFromGoogleOAuth2(credentials))

Screenshots
Screen Shot 2020-04-24 at 5 28 51 PM

If applicable, add screenshots to help explain your problem.

Environment info:
Tested and reproduced both locally
(MacOS High Sierra, 10.13.6, MBP mid 2014, Python 3.7.7, Pipenv, executed via Serverless Invoke Local
and in a Google Colab
(Python 3.6.9)

The breaking change is for every version after (and including) 3.4.0.

@alecbw
Copy link
Author

alecbw commented Apr 25, 2020

Guessing based on these commits that oauth2client was intentionally deprecated and that's causing this auth to fail

If that's the case, can you:

  • Update the error message to be more clear? It's currently Credentials need to be from either oauth2client or from google-auth.
  • Provide an example of using service_account.Credentials.from_service_account_info? There is only a from_service_account_file example

@alecbw
Copy link
Author

alecbw commented Apr 25, 2020

Closing this now, the solution was right in front of my face:

    auth = {
        "private_key": os.environ["GSHEETS_PRIVATE_KEY"].replace("\\n", "\n").replace('"', ''),
        "client_email": os.environ["GSHEETS_CLIENT_EMAIL"],
        "token_uri": "https://oauth2.googleapis.com/token",
    }
    scopes = ['https://www.googleapis.com/auth/spreadsheets']
    credentials = service_account.Credentials.from_service_account_info(auth, scopes=scopes)
    gc = gspread.authorize(credentials)

Still think it's worth doing the two things in the comment above

@alecbw alecbw closed this as completed Apr 25, 2020
@burnash
Copy link
Owner

burnash commented Apr 27, 2020

Thank you for the input and for the detailed report. Totally agree on the suggestions.

The authentication topic is broad. Currently, I'm trying to make the auth as simple as possible (#762, #768).

The library will greatly benefit if we have more cases covered in docs. Unfortunately, I can't cover a lot of cases from my own experience.

Update the error message to be more clear? It's currently Credentials need to be from either oauth2client or from google-auth.

Could you suggest a better message? This is something we can implement right away.

Provide an example of using service_account.Credentials.from_service_account_info? There is only a from_service_account_file example

I'm open to accepting a PR for this one. As I said, more detailed docs for auth are certainly needed. We can start by adding something like "Custom Authentication" to Authentication docs.

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

2 participants